/src/keystone/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- HexagonAsmParser.cpp - Parse Hexagon asm to MCInst instructions----===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #define DEBUG_TYPE "mcasmparser" |
11 | | |
12 | | #include "Hexagon.h" |
13 | | #include "HexagonTargetStreamer.h" |
14 | | #include "MCTargetDesc/HexagonBaseInfo.h" |
15 | | #include "MCTargetDesc/HexagonMCAsmInfo.h" |
16 | | #include "MCTargetDesc/HexagonMCChecker.h" |
17 | | #include "MCTargetDesc/HexagonMCExpr.h" |
18 | | #include "MCTargetDesc/HexagonMCShuffler.h" |
19 | | #include "MCTargetDesc/HexagonMCTargetDesc.h" |
20 | | #include "MCTargetDesc/HexagonShuffler.h" |
21 | | #include "llvm/ADT/SmallString.h" |
22 | | #include "llvm/ADT/SmallVector.h" |
23 | | #include "llvm/ADT/StringExtras.h" |
24 | | #include "llvm/ADT/Twine.h" |
25 | | #include "llvm/MC/MCContext.h" |
26 | | #include "llvm/MC/MCELFStreamer.h" |
27 | | #include "llvm/MC/MCExpr.h" |
28 | | #include "llvm/MC/MCInst.h" |
29 | | #include "llvm/MC/MCParser/MCAsmLexer.h" |
30 | | #include "llvm/MC/MCParser/MCAsmParser.h" |
31 | | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
32 | | #include "llvm/MC/MCParser/MCTargetAsmParser.h" |
33 | | #include "llvm/MC/MCSectionELF.h" |
34 | | #include "llvm/MC/MCStreamer.h" |
35 | | #include "llvm/MC/MCSubtargetInfo.h" |
36 | | #include "llvm/Support/Debug.h" |
37 | | #include "llvm/Support/ELF.h" |
38 | | #include "llvm/Support/Format.h" |
39 | | #include "llvm/Support/MemoryBuffer.h" |
40 | | #include "llvm/Support/SourceMgr.h" |
41 | | #include "llvm/Support/TargetRegistry.h" |
42 | | #include "llvm/Support/raw_ostream.h" |
43 | | #include <sstream> |
44 | | |
45 | | #include "keystone/hexagon.h" |
46 | | |
47 | | using namespace llvm_ks; |
48 | | |
49 | | static bool WarnMissingParenthesis = true; |
50 | | static bool ErrorMissingParenthesis = false; |
51 | | static bool WarnSignedMismatch = true; |
52 | | static bool WarnNoncontigiousRegister = true; |
53 | | static bool ErrorNoncontigiousRegister = false; |
54 | | |
55 | | namespace { |
56 | | struct HexagonOperand; |
57 | | |
58 | | class HexagonAsmParser : public MCTargetAsmParser { |
59 | | |
60 | 0 | HexagonTargetStreamer &getTargetStreamer() { |
61 | 0 | MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer(); |
62 | 0 | return static_cast<HexagonTargetStreamer &>(TS); |
63 | 0 | } |
64 | | |
65 | | MCAsmParser &Parser; |
66 | | MCAssembler *Assembler; |
67 | | MCInstrInfo const &MCII; |
68 | | MCInst MCB; |
69 | | bool InBrackets; |
70 | | |
71 | 785k | MCAsmParser &getParser() const { return Parser; } |
72 | 0 | MCAssembler *getAssembler() const { return Assembler; } |
73 | 2.88M | MCAsmLexer &getLexer() const { return Parser.getLexer(); } |
74 | | |
75 | 2.79k | bool equalIsAsmAssignment() override { return false; } |
76 | | bool isLabel(AsmToken &Token, bool &valid) override; |
77 | | |
78 | 2.00k | void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } |
79 | 570 | bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } |
80 | | bool ParseDirectiveFalign(unsigned Size, SMLoc L); |
81 | | |
82 | | virtual bool ParseRegister(unsigned &RegNo, |
83 | | SMLoc &StartLoc, |
84 | | SMLoc &EndLoc, unsigned int &ErrorCode) override; |
85 | | bool ParseDirectiveSubsection(SMLoc L); |
86 | | bool ParseDirectiveValue(unsigned Size, SMLoc L); |
87 | | bool ParseDirectiveComm(bool IsLocal, SMLoc L); |
88 | | bool RegisterMatchesArch(unsigned MatchNum) const; |
89 | | |
90 | | bool matchBundleOptions(); |
91 | | bool handleNoncontigiousRegister(bool Contigious, SMLoc &Loc); |
92 | | bool finishBundle(SMLoc IDLoc, MCStreamer &Out, unsigned &KsError); |
93 | | void canonicalizeImmediates(MCInst &MCI); |
94 | | bool matchOneInstruction(MCInst &MCB, SMLoc IDLoc, |
95 | | OperandVector &InstOperands, uint64_t &ErrorInfo, |
96 | | bool MatchingInlineAsm, bool &MustExtend, unsigned int &ErrorCode); |
97 | | |
98 | | bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
99 | | OperandVector &Operands, MCStreamer &Out, |
100 | | uint64_t &ErrorInfo, bool MatchingInlineAsm, unsigned int &ErrorCode, uint64_t &Address) override; |
101 | | |
102 | | unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) override; |
103 | | void OutOfRange(SMLoc IDLoc, long long Val, long long Max); |
104 | | int processInstruction(MCInst &Inst, OperandVector const &Operands, |
105 | | SMLoc IDLoc, bool &MustExtend); |
106 | | |
107 | | // Check if we have an assembler and, if so, set the ELF e_header flags. |
108 | 0 | void chksetELFHeaderEFlags(unsigned flags) { |
109 | 0 | if (getAssembler()) |
110 | 0 | getAssembler()->setELFHeaderEFlags(flags); |
111 | 0 | } |
112 | | |
113 | | /// @name Auto-generated Match Functions |
114 | | /// { |
115 | | |
116 | | #define GET_ASSEMBLER_HEADER |
117 | | #include "HexagonGenAsmMatcher.inc" |
118 | | |
119 | | /// } |
120 | | |
121 | | public: |
122 | | HexagonAsmParser(const MCSubtargetInfo &_STI, MCAsmParser &_Parser, |
123 | | const MCInstrInfo &MII, const MCTargetOptions &Options) |
124 | 3.00k | : MCTargetAsmParser(Options, _STI), Parser(_Parser), |
125 | 3.00k | MCII (MII), MCB(HexagonMCInstrInfo::createBundle()), InBrackets(false) { |
126 | 3.00k | setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); |
127 | | |
128 | 3.00k | MCAsmParserExtension::Initialize(_Parser); |
129 | | |
130 | 3.00k | Assembler = nullptr; |
131 | | // FIXME: need better way to detect AsmStreamer (upstream removed getKind()) |
132 | 3.00k | if (!Parser.getStreamer().hasRawTextSupport()) { |
133 | 3.00k | MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer()); |
134 | 3.00k | Assembler = &MES->getAssembler(); |
135 | 3.00k | } |
136 | 3.00k | } |
137 | | |
138 | | bool mustExtend(OperandVector &Operands); |
139 | | bool splitIdentifier(OperandVector &Operands); |
140 | | bool parseOperand(OperandVector &Operands); |
141 | | bool parseInstruction(OperandVector &Operands); |
142 | | bool implicitExpressionLocation(OperandVector &Operands); |
143 | | bool parseExpressionOrOperand(OperandVector &Operands); |
144 | | bool parseExpression(MCExpr const *& Expr); |
145 | | virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
146 | | SMLoc NameLoc, OperandVector &Operands, unsigned int &ErrorCode) override |
147 | 0 | { |
148 | 0 | llvm_unreachable("Unimplemented"); |
149 | 0 | } |
150 | | virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
151 | | AsmToken ID, OperandVector &Operands, unsigned int &ErrorCode) override; |
152 | | |
153 | | virtual bool ParseDirective(AsmToken DirectiveID) override; |
154 | | }; |
155 | | |
156 | | /// HexagonOperand - Instances of this class represent a parsed Hexagon machine |
157 | | /// instruction. |
158 | | struct HexagonOperand : public MCParsedAsmOperand { |
159 | | enum KindTy { Token, Immediate, Register } Kind; |
160 | | |
161 | | SMLoc StartLoc, EndLoc; |
162 | | |
163 | | struct TokTy { |
164 | | const char *Data; |
165 | | unsigned Length; |
166 | | }; |
167 | | |
168 | | struct RegTy { |
169 | | unsigned RegNum; |
170 | | }; |
171 | | |
172 | | struct ImmTy { |
173 | | const MCExpr *Val; |
174 | | bool MustExtend; |
175 | | }; |
176 | | |
177 | | struct InstTy { |
178 | | OperandVector *SubInsts; |
179 | | }; |
180 | | |
181 | | union { |
182 | | struct TokTy Tok; |
183 | | struct RegTy Reg; |
184 | | struct ImmTy Imm; |
185 | | }; |
186 | | |
187 | 517k | HexagonOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} |
188 | | |
189 | | public: |
190 | 0 | HexagonOperand(const HexagonOperand &o) : MCParsedAsmOperand() { |
191 | 0 | Kind = o.Kind; |
192 | 0 | StartLoc = o.StartLoc; |
193 | 0 | EndLoc = o.EndLoc; |
194 | 0 | switch (Kind) { |
195 | 0 | case Register: |
196 | 0 | Reg = o.Reg; |
197 | 0 | break; |
198 | 0 | case Immediate: |
199 | 0 | Imm = o.Imm; |
200 | 0 | break; |
201 | 0 | case Token: |
202 | 0 | Tok = o.Tok; |
203 | 0 | break; |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | | /// getStartLoc - Get the location of the first token of this operand. |
208 | 0 | SMLoc getStartLoc() const { return StartLoc; } |
209 | | |
210 | | /// getEndLoc - Get the location of the last token of this operand. |
211 | 0 | SMLoc getEndLoc() const { return EndLoc; } |
212 | | |
213 | 434k | unsigned getReg() const { |
214 | 434k | assert(Kind == Register && "Invalid access!"); |
215 | 434k | return Reg.RegNum; |
216 | 434k | } |
217 | | |
218 | 6.01k | const MCExpr *getImm() const { |
219 | 6.01k | assert(Kind == Immediate && "Invalid access!"); |
220 | 6.01k | return Imm.Val; |
221 | 6.01k | } |
222 | | |
223 | 3.37M | bool isToken() const { return Kind == Token; } |
224 | 16.8k | bool isImm() const { return Kind == Immediate; } |
225 | 0 | bool isMem() const { llvm_unreachable("No isMem"); } |
226 | 431k | bool isReg() const { return Kind == Register; } |
227 | | |
228 | | bool CheckImmRange(int immBits, int zeroBits, bool isSigned, |
229 | 2.04k | bool isRelocatable, bool Extendable) const { |
230 | 2.04k | if (Kind == Immediate) { |
231 | 2.04k | const MCExpr *myMCExpr = getImm(); |
232 | 2.04k | if (Imm.MustExtend && !Extendable) |
233 | 3 | return false; |
234 | 2.04k | int64_t Res; |
235 | 2.04k | if (myMCExpr->evaluateAsAbsolute(Res)) { |
236 | 1.92k | int bits = immBits + zeroBits; |
237 | | // Field bit range is zerobits + bits |
238 | | // zeroBits must be 0 |
239 | 1.92k | if (Res & ((1 << zeroBits) - 1)) |
240 | 0 | return false; |
241 | 1.92k | if (isSigned) { |
242 | 1.89k | if (Res < (1LL << (bits - 1)) && Res >= -(1LL << (bits - 1))) |
243 | 1.87k | return true; |
244 | 1.89k | } else { |
245 | 28 | if (bits == 64) |
246 | 16 | return true; |
247 | 12 | if (Res >= 0) |
248 | 6 | return ((uint64_t)Res < (uint64_t)(1ULL << bits)) ? true : false; |
249 | 6 | else { |
250 | 6 | const int64_t high_bit_set = 1ULL << 63; |
251 | 6 | const uint64_t mask = (high_bit_set >> (63 - bits)); |
252 | 6 | return (((uint64_t)Res & mask) == mask) ? true : false; |
253 | 6 | } |
254 | 12 | } |
255 | 1.92k | } else if (myMCExpr->getKind() == MCExpr::SymbolRef && isRelocatable) |
256 | 25 | return true; |
257 | 95 | else if (myMCExpr->getKind() == MCExpr::Binary || |
258 | 95 | myMCExpr->getKind() == MCExpr::Unary) |
259 | 95 | return true; |
260 | 2.04k | } |
261 | 16 | return false; |
262 | 2.04k | } |
263 | | |
264 | 0 | bool isf32Ext() const { return false; } |
265 | 0 | bool iss32Imm() const { return CheckImmRange(32, 0, true, true, false); } |
266 | 0 | bool iss8Imm() const { return CheckImmRange(8, 0, true, false, false); } |
267 | 17 | bool iss8Imm64() const { return CheckImmRange(8, 0, true, true, false); } |
268 | 0 | bool iss7Imm() const { return CheckImmRange(7, 0, true, false, false); } |
269 | 0 | bool iss6Imm() const { return CheckImmRange(6, 0, true, false, false); } |
270 | 0 | bool iss4Imm() const { return CheckImmRange(4, 0, true, false, false); } |
271 | 0 | bool iss4_0Imm() const { return CheckImmRange(4, 0, true, false, false); } |
272 | 0 | bool iss4_1Imm() const { return CheckImmRange(4, 1, true, false, false); } |
273 | 0 | bool iss4_2Imm() const { return CheckImmRange(4, 2, true, false, false); } |
274 | 0 | bool iss4_3Imm() const { return CheckImmRange(4, 3, true, false, false); } |
275 | 0 | bool iss4_6Imm() const { return CheckImmRange(4, 0, true, false, false); } |
276 | 0 | bool iss3_6Imm() const { return CheckImmRange(3, 0, true, false, false); } |
277 | 0 | bool iss3Imm() const { return CheckImmRange(3, 0, true, false, false); } |
278 | | |
279 | 16 | bool isu64Imm() const { return CheckImmRange(64, 0, false, true, true); } |
280 | 0 | bool isu32Imm() const { return CheckImmRange(32, 0, false, true, false); } |
281 | 0 | bool isu26_6Imm() const { return CheckImmRange(26, 6, false, true, false); } |
282 | 17 | bool isu16Imm() const { return CheckImmRange(16, 0, false, true, false); } |
283 | 0 | bool isu16_0Imm() const { return CheckImmRange(16, 0, false, true, false); } |
284 | 0 | bool isu16_1Imm() const { return CheckImmRange(16, 1, false, true, false); } |
285 | 0 | bool isu16_2Imm() const { return CheckImmRange(16, 2, false, true, false); } |
286 | 0 | bool isu16_3Imm() const { return CheckImmRange(16, 3, false, true, false); } |
287 | 0 | bool isu11_3Imm() const { return CheckImmRange(11, 3, false, false, false); } |
288 | 0 | bool isu6_0Imm() const { return CheckImmRange(6, 0, false, false, false); } |
289 | 0 | bool isu6_1Imm() const { return CheckImmRange(6, 1, false, false, false); } |
290 | 0 | bool isu6_2Imm() const { return CheckImmRange(6, 2, false, false, false); } |
291 | 0 | bool isu6_3Imm() const { return CheckImmRange(6, 3, false, false, false); } |
292 | 3 | bool isu10Imm() const { return CheckImmRange(10, 0, false, false, false); } |
293 | 0 | bool isu9Imm() const { return CheckImmRange(9, 0, false, false, false); } |
294 | 0 | bool isu8Imm() const { return CheckImmRange(8, 0, false, false, false); } |
295 | 0 | bool isu7Imm() const { return CheckImmRange(7, 0, false, false, false); } |
296 | 11 | bool isu6Imm() const { return CheckImmRange(6, 0, false, false, false); } |
297 | 0 | bool isu5Imm() const { return CheckImmRange(5, 0, false, false, false); } |
298 | 0 | bool isu4Imm() const { return CheckImmRange(4, 0, false, false, false); } |
299 | 0 | bool isu3Imm() const { return CheckImmRange(3, 0, false, false, false); } |
300 | 0 | bool isu2Imm() const { return CheckImmRange(2, 0, false, false, false); } |
301 | 0 | bool isu1Imm() const { return CheckImmRange(1, 0, false, false, false); } |
302 | | |
303 | 0 | bool ism6Imm() const { return CheckImmRange(6, 0, false, false, false); } |
304 | 0 | bool isn8Imm() const { return CheckImmRange(8, 0, false, false, false); } |
305 | | |
306 | 1.97k | bool iss16Ext() const { return CheckImmRange(16 + 26, 0, true, true, true); } |
307 | 1 | bool iss12Ext() const { return CheckImmRange(12 + 26, 0, true, true, true); } |
308 | 0 | bool iss10Ext() const { return CheckImmRange(10 + 26, 0, true, true, true); } |
309 | 0 | bool iss9Ext() const { return CheckImmRange(9 + 26, 0, true, true, true); } |
310 | 0 | bool iss8Ext() const { return CheckImmRange(8 + 26, 0, true, true, true); } |
311 | 0 | bool iss7Ext() const { return CheckImmRange(7 + 26, 0, true, true, true); } |
312 | 0 | bool iss6Ext() const { return CheckImmRange(6 + 26, 0, true, true, true); } |
313 | 0 | bool iss11_0Ext() const { |
314 | 0 | return CheckImmRange(11 + 26, 0, true, true, true); |
315 | 0 | } |
316 | 0 | bool iss11_1Ext() const { |
317 | 0 | return CheckImmRange(11 + 26, 1, true, true, true); |
318 | 0 | } |
319 | 0 | bool iss11_2Ext() const { |
320 | 0 | return CheckImmRange(11 + 26, 2, true, true, true); |
321 | 0 | } |
322 | 0 | bool iss11_3Ext() const { |
323 | 0 | return CheckImmRange(11 + 26, 3, true, true, true); |
324 | 0 | } |
325 | | |
326 | 0 | bool isu6Ext() const { return CheckImmRange(6 + 26, 0, false, true, true); } |
327 | 0 | bool isu7Ext() const { return CheckImmRange(7 + 26, 0, false, true, true); } |
328 | 0 | bool isu8Ext() const { return CheckImmRange(8 + 26, 0, false, true, true); } |
329 | 0 | bool isu9Ext() const { return CheckImmRange(9 + 26, 0, false, true, true); } |
330 | 0 | bool isu10Ext() const { return CheckImmRange(10 + 26, 0, false, true, true); } |
331 | 0 | bool isu6_0Ext() const { return CheckImmRange(6 + 26, 0, false, true, true); } |
332 | 0 | bool isu6_1Ext() const { return CheckImmRange(6 + 26, 1, false, true, true); } |
333 | 0 | bool isu6_2Ext() const { return CheckImmRange(6 + 26, 2, false, true, true); } |
334 | 0 | bool isu6_3Ext() const { return CheckImmRange(6 + 26, 3, false, true, true); } |
335 | 0 | bool isu32MustExt() const { return isImm() && Imm.MustExtend; } |
336 | | |
337 | 3.55k | void addRegOperands(MCInst &Inst, unsigned N) const { |
338 | 3.55k | assert(N == 1 && "Invalid number of operands!"); |
339 | 3.55k | Inst.addOperand(MCOperand::createReg(getReg())); |
340 | 3.55k | } |
341 | | |
342 | 2.00k | void addImmOperands(MCInst &Inst, unsigned N) const { |
343 | 2.00k | assert(N == 1 && "Invalid number of operands!"); |
344 | 2.00k | Inst.addOperand(MCOperand::createExpr(getImm())); |
345 | 2.00k | } |
346 | | |
347 | 1.96k | void addSignedImmOperands(MCInst &Inst, unsigned N) const { |
348 | 1.96k | assert(N == 1 && "Invalid number of operands!"); |
349 | 1.96k | MCExpr const *Expr = getImm(); |
350 | 1.96k | int64_t Value; |
351 | 1.96k | if (!Expr->evaluateAsAbsolute(Value)) { |
352 | 98 | Inst.addOperand(MCOperand::createExpr(Expr)); |
353 | 98 | return; |
354 | 98 | } |
355 | 1.87k | int64_t Extended = SignExtend64 (Value, 32); |
356 | 1.87k | if ((Extended < 0) == (Value < 0)) { |
357 | 1.86k | Inst.addOperand(MCOperand::createExpr(Expr)); |
358 | 1.86k | return; |
359 | 1.86k | } |
360 | | // Flip bit 33 to signal signed unsigned mismatch |
361 | 3 | Extended ^= 0x100000000; |
362 | 3 | Inst.addOperand(MCOperand::createImm(Extended)); |
363 | 3 | } |
364 | | |
365 | 0 | void addf32ExtOperands(MCInst &Inst, unsigned N) const { |
366 | 0 | addImmOperands(Inst, N); |
367 | 0 | } |
368 | | |
369 | 0 | void adds32ImmOperands(MCInst &Inst, unsigned N) const { |
370 | 0 | addSignedImmOperands(Inst, N); |
371 | 0 | } |
372 | 0 | void adds8ImmOperands(MCInst &Inst, unsigned N) const { |
373 | 0 | addSignedImmOperands(Inst, N); |
374 | 0 | } |
375 | 1 | void adds8Imm64Operands(MCInst &Inst, unsigned N) const { |
376 | 1 | addSignedImmOperands(Inst, N); |
377 | 1 | } |
378 | 0 | void adds6ImmOperands(MCInst &Inst, unsigned N) const { |
379 | 0 | addSignedImmOperands(Inst, N); |
380 | 0 | } |
381 | 0 | void adds4ImmOperands(MCInst &Inst, unsigned N) const { |
382 | 0 | addSignedImmOperands(Inst, N); |
383 | 0 | } |
384 | 0 | void adds4_0ImmOperands(MCInst &Inst, unsigned N) const { |
385 | 0 | addSignedImmOperands(Inst, N); |
386 | 0 | } |
387 | 0 | void adds4_1ImmOperands(MCInst &Inst, unsigned N) const { |
388 | 0 | addSignedImmOperands(Inst, N); |
389 | 0 | } |
390 | 0 | void adds4_2ImmOperands(MCInst &Inst, unsigned N) const { |
391 | 0 | addSignedImmOperands(Inst, N); |
392 | 0 | } |
393 | 0 | void adds4_3ImmOperands(MCInst &Inst, unsigned N) const { |
394 | 0 | addSignedImmOperands(Inst, N); |
395 | 0 | } |
396 | 0 | void adds3ImmOperands(MCInst &Inst, unsigned N) const { |
397 | 0 | addSignedImmOperands(Inst, N); |
398 | 0 | } |
399 | | |
400 | 16 | void addu64ImmOperands(MCInst &Inst, unsigned N) const { |
401 | 16 | addImmOperands(Inst, N); |
402 | 16 | } |
403 | 0 | void addu32ImmOperands(MCInst &Inst, unsigned N) const { |
404 | 0 | addImmOperands(Inst, N); |
405 | 0 | } |
406 | 0 | void addu26_6ImmOperands(MCInst &Inst, unsigned N) const { |
407 | 0 | addImmOperands(Inst, N); |
408 | 0 | } |
409 | 17 | void addu16ImmOperands(MCInst &Inst, unsigned N) const { |
410 | 17 | addImmOperands(Inst, N); |
411 | 17 | } |
412 | 0 | void addu16_0ImmOperands(MCInst &Inst, unsigned N) const { |
413 | 0 | addImmOperands(Inst, N); |
414 | 0 | } |
415 | 0 | void addu16_1ImmOperands(MCInst &Inst, unsigned N) const { |
416 | 0 | addImmOperands(Inst, N); |
417 | 0 | } |
418 | 0 | void addu16_2ImmOperands(MCInst &Inst, unsigned N) const { |
419 | 0 | addImmOperands(Inst, N); |
420 | 0 | } |
421 | 0 | void addu16_3ImmOperands(MCInst &Inst, unsigned N) const { |
422 | 0 | addImmOperands(Inst, N); |
423 | 0 | } |
424 | 0 | void addu11_3ImmOperands(MCInst &Inst, unsigned N) const { |
425 | 0 | addImmOperands(Inst, N); |
426 | 0 | } |
427 | 0 | void addu10ImmOperands(MCInst &Inst, unsigned N) const { |
428 | 0 | addImmOperands(Inst, N); |
429 | 0 | } |
430 | 0 | void addu9ImmOperands(MCInst &Inst, unsigned N) const { |
431 | 0 | addImmOperands(Inst, N); |
432 | 0 | } |
433 | 0 | void addu8ImmOperands(MCInst &Inst, unsigned N) const { |
434 | 0 | addImmOperands(Inst, N); |
435 | 0 | } |
436 | 0 | void addu7ImmOperands(MCInst &Inst, unsigned N) const { |
437 | 0 | addImmOperands(Inst, N); |
438 | 0 | } |
439 | 0 | void addu6ImmOperands(MCInst &Inst, unsigned N) const { |
440 | 0 | addImmOperands(Inst, N); |
441 | 0 | } |
442 | 0 | void addu6_0ImmOperands(MCInst &Inst, unsigned N) const { |
443 | 0 | addImmOperands(Inst, N); |
444 | 0 | } |
445 | 0 | void addu6_1ImmOperands(MCInst &Inst, unsigned N) const { |
446 | 0 | addImmOperands(Inst, N); |
447 | 0 | } |
448 | 0 | void addu6_2ImmOperands(MCInst &Inst, unsigned N) const { |
449 | 0 | addImmOperands(Inst, N); |
450 | 0 | } |
451 | 0 | void addu6_3ImmOperands(MCInst &Inst, unsigned N) const { |
452 | 0 | addImmOperands(Inst, N); |
453 | 0 | } |
454 | 0 | void addu5ImmOperands(MCInst &Inst, unsigned N) const { |
455 | 0 | addImmOperands(Inst, N); |
456 | 0 | } |
457 | 0 | void addu4ImmOperands(MCInst &Inst, unsigned N) const { |
458 | 0 | addImmOperands(Inst, N); |
459 | 0 | } |
460 | 0 | void addu3ImmOperands(MCInst &Inst, unsigned N) const { |
461 | 0 | addImmOperands(Inst, N); |
462 | 0 | } |
463 | 0 | void addu2ImmOperands(MCInst &Inst, unsigned N) const { |
464 | 0 | addImmOperands(Inst, N); |
465 | 0 | } |
466 | 0 | void addu1ImmOperands(MCInst &Inst, unsigned N) const { |
467 | 0 | addImmOperands(Inst, N); |
468 | 0 | } |
469 | | |
470 | 0 | void addm6ImmOperands(MCInst &Inst, unsigned N) const { |
471 | 0 | addImmOperands(Inst, N); |
472 | 0 | } |
473 | 0 | void addn8ImmOperands(MCInst &Inst, unsigned N) const { |
474 | 0 | addImmOperands(Inst, N); |
475 | 0 | } |
476 | | |
477 | 1.96k | void adds16ExtOperands(MCInst &Inst, unsigned N) const { |
478 | 1.96k | addSignedImmOperands(Inst, N); |
479 | 1.96k | } |
480 | 1 | void adds12ExtOperands(MCInst &Inst, unsigned N) const { |
481 | 1 | addSignedImmOperands(Inst, N); |
482 | 1 | } |
483 | 0 | void adds10ExtOperands(MCInst &Inst, unsigned N) const { |
484 | 0 | addSignedImmOperands(Inst, N); |
485 | 0 | } |
486 | 0 | void adds9ExtOperands(MCInst &Inst, unsigned N) const { |
487 | 0 | addSignedImmOperands(Inst, N); |
488 | 0 | } |
489 | 0 | void adds8ExtOperands(MCInst &Inst, unsigned N) const { |
490 | 0 | addSignedImmOperands(Inst, N); |
491 | 0 | } |
492 | 0 | void adds6ExtOperands(MCInst &Inst, unsigned N) const { |
493 | 0 | addSignedImmOperands(Inst, N); |
494 | 0 | } |
495 | 0 | void adds11_0ExtOperands(MCInst &Inst, unsigned N) const { |
496 | 0 | addSignedImmOperands(Inst, N); |
497 | 0 | } |
498 | 0 | void adds11_1ExtOperands(MCInst &Inst, unsigned N) const { |
499 | 0 | addSignedImmOperands(Inst, N); |
500 | 0 | } |
501 | 0 | void adds11_2ExtOperands(MCInst &Inst, unsigned N) const { |
502 | 0 | addSignedImmOperands(Inst, N); |
503 | 0 | } |
504 | 0 | void adds11_3ExtOperands(MCInst &Inst, unsigned N) const { |
505 | 0 | addSignedImmOperands(Inst, N); |
506 | 0 | } |
507 | | |
508 | 0 | void addu6ExtOperands(MCInst &Inst, unsigned N) const { |
509 | 0 | addImmOperands(Inst, N); |
510 | 0 | } |
511 | 0 | void addu7ExtOperands(MCInst &Inst, unsigned N) const { |
512 | 0 | addImmOperands(Inst, N); |
513 | 0 | } |
514 | 0 | void addu8ExtOperands(MCInst &Inst, unsigned N) const { |
515 | 0 | addImmOperands(Inst, N); |
516 | 0 | } |
517 | 0 | void addu9ExtOperands(MCInst &Inst, unsigned N) const { |
518 | 0 | addImmOperands(Inst, N); |
519 | 0 | } |
520 | 0 | void addu10ExtOperands(MCInst &Inst, unsigned N) const { |
521 | 0 | addImmOperands(Inst, N); |
522 | 0 | } |
523 | 0 | void addu6_0ExtOperands(MCInst &Inst, unsigned N) const { |
524 | 0 | addImmOperands(Inst, N); |
525 | 0 | } |
526 | 0 | void addu6_1ExtOperands(MCInst &Inst, unsigned N) const { |
527 | 0 | addImmOperands(Inst, N); |
528 | 0 | } |
529 | 0 | void addu6_2ExtOperands(MCInst &Inst, unsigned N) const { |
530 | 0 | addImmOperands(Inst, N); |
531 | 0 | } |
532 | 0 | void addu6_3ExtOperands(MCInst &Inst, unsigned N) const { |
533 | 0 | addImmOperands(Inst, N); |
534 | 0 | } |
535 | 0 | void addu32MustExtOperands(MCInst &Inst, unsigned N) const { |
536 | 0 | addImmOperands(Inst, N); |
537 | 0 | } |
538 | | |
539 | 0 | void adds4_6ImmOperands(MCInst &Inst, unsigned N) const { |
540 | 0 | assert(N == 1 && "Invalid number of operands!"); |
541 | 0 | const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); |
542 | 0 | Inst.addOperand(MCOperand::createImm(CE->getValue() * 64)); |
543 | 0 | } |
544 | | |
545 | 0 | void adds3_6ImmOperands(MCInst &Inst, unsigned N) const { |
546 | 0 | assert(N == 1 && "Invalid number of operands!"); |
547 | 0 | const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); |
548 | 0 | Inst.addOperand(MCOperand::createImm(CE->getValue() * 64)); |
549 | 0 | } |
550 | | |
551 | 2.59M | StringRef getToken() const { |
552 | 2.59M | assert(Kind == Token && "Invalid access!"); |
553 | 2.59M | return StringRef(Tok.Data, Tok.Length); |
554 | 2.59M | } |
555 | | |
556 | | virtual void print(raw_ostream &OS) const; |
557 | | |
558 | 455k | static std::unique_ptr<HexagonOperand> CreateToken(StringRef Str, SMLoc S) { |
559 | 455k | HexagonOperand *Op = new HexagonOperand(Token); |
560 | 455k | Op->Tok.Data = Str.data(); |
561 | 455k | Op->Tok.Length = Str.size(); |
562 | 455k | Op->StartLoc = S; |
563 | 455k | Op->EndLoc = S; |
564 | 455k | return std::unique_ptr<HexagonOperand>(Op); |
565 | 455k | } |
566 | | |
567 | | static std::unique_ptr<HexagonOperand> CreateReg(unsigned RegNum, SMLoc S, |
568 | 17.0k | SMLoc E) { |
569 | 17.0k | HexagonOperand *Op = new HexagonOperand(Register); |
570 | 17.0k | Op->Reg.RegNum = RegNum; |
571 | 17.0k | Op->StartLoc = S; |
572 | 17.0k | Op->EndLoc = E; |
573 | 17.0k | return std::unique_ptr<HexagonOperand>(Op); |
574 | 17.0k | } |
575 | | |
576 | | static std::unique_ptr<HexagonOperand> CreateImm(const MCExpr *Val, SMLoc S, |
577 | 44.5k | SMLoc E) { |
578 | 44.5k | HexagonOperand *Op = new HexagonOperand(Immediate); |
579 | 44.5k | Op->Imm.Val = Val; |
580 | 44.5k | Op->Imm.MustExtend = false; |
581 | 44.5k | Op->StartLoc = S; |
582 | 44.5k | Op->EndLoc = E; |
583 | 44.5k | return std::unique_ptr<HexagonOperand>(Op); |
584 | 44.5k | } |
585 | | }; |
586 | | |
587 | | } // end anonymous namespace. |
588 | | |
589 | 0 | void HexagonOperand::print(raw_ostream &OS) const { |
590 | 0 | switch (Kind) { |
591 | 0 | case Immediate: |
592 | 0 | getImm()->print(OS, nullptr); |
593 | 0 | break; |
594 | 0 | case Register: |
595 | 0 | OS << "<register R"; |
596 | 0 | OS << getReg() << ">"; |
597 | 0 | break; |
598 | 0 | case Token: |
599 | 0 | OS << "'" << getToken() << "'"; |
600 | 0 | break; |
601 | 0 | } |
602 | 0 | } |
603 | | |
604 | | /// @name Auto-generated Match Functions |
605 | | static unsigned MatchRegisterName(StringRef Name); |
606 | | |
607 | | bool HexagonAsmParser::finishBundle(SMLoc IDLoc, MCStreamer &Out, unsigned &KsError) |
608 | 3.25k | { |
609 | 3.25k | DEBUG(dbgs() << "Bundle:"); |
610 | 3.25k | DEBUG(MCB.dump_pretty(dbgs())); |
611 | 3.25k | DEBUG(dbgs() << "--\n"); |
612 | | |
613 | | // Check the bundle for errors. |
614 | 3.25k | const MCRegisterInfo *RI = getContext().getRegisterInfo(); |
615 | 3.25k | HexagonMCChecker Check(MCII, getSTI(), MCB, MCB, *RI); |
616 | | |
617 | 3.25k | bool CheckOk = HexagonMCInstrInfo::canonicalizePacket(MCII, getSTI(), |
618 | 3.25k | getContext(), MCB, |
619 | 3.25k | &Check); |
620 | | |
621 | 3.67k | while (Check.getNextErrInfo() == true) { |
622 | 411 | unsigned Reg = Check.getErrRegister(); |
623 | 411 | Twine R(RI->getName(Reg)); |
624 | | |
625 | 411 | uint64_t Err = Check.getError(); |
626 | 411 | if (Err != HexagonMCErrInfo::CHECK_SUCCESS) { |
627 | 411 | if (HexagonMCErrInfo::CHECK_ERROR_BRANCHES & Err) |
628 | 17 | Error(IDLoc, |
629 | 17 | "unconditional branch cannot precede another branch in packet"); |
630 | | |
631 | 411 | if (HexagonMCErrInfo::CHECK_ERROR_NEWP & Err || |
632 | 411 | HexagonMCErrInfo::CHECK_ERROR_NEWV & Err) |
633 | 0 | Error(IDLoc, "register `" + R + |
634 | 0 | "' used with `.new' " |
635 | 0 | "but not validly modified in the same packet"); |
636 | | |
637 | 411 | if (HexagonMCErrInfo::CHECK_ERROR_REGISTERS & Err) |
638 | 40 | Error(IDLoc, "register `" + R + "' modified more than once"); |
639 | | |
640 | 411 | if (HexagonMCErrInfo::CHECK_ERROR_READONLY & Err) |
641 | 271 | Error(IDLoc, "cannot write to read-only register `" + R + "'"); |
642 | | |
643 | 411 | if (HexagonMCErrInfo::CHECK_ERROR_LOOP & Err) |
644 | 0 | Error(IDLoc, "loop-setup and some branch instructions " |
645 | 0 | "cannot be in the same packet"); |
646 | | |
647 | 411 | if (HexagonMCErrInfo::CHECK_ERROR_ENDLOOP & Err) { |
648 | 0 | Twine N(HexagonMCInstrInfo::isInnerLoop(MCB) ? '0' : '1'); |
649 | 0 | Error(IDLoc, "packet marked with `:endloop" + N + "' " + |
650 | 0 | "cannot contain instructions that modify register " + |
651 | 0 | "`" + R + "'"); |
652 | 0 | } |
653 | | |
654 | 411 | if (HexagonMCErrInfo::CHECK_ERROR_SOLO & Err) |
655 | 0 | Error(IDLoc, |
656 | 0 | "instruction cannot appear in packet with other instructions"); |
657 | | |
658 | 411 | if (HexagonMCErrInfo::CHECK_ERROR_NOSLOTS & Err) |
659 | 41 | Error(IDLoc, "too many slots used in packet"); |
660 | | |
661 | 411 | if (Err & HexagonMCErrInfo::CHECK_ERROR_SHUFFLE) { |
662 | 42 | uint64_t Erm = Check.getShuffleError(); |
663 | | |
664 | 42 | if (HexagonShuffler::SHUFFLE_ERROR_INVALID == Erm) |
665 | 0 | Error(IDLoc, "invalid instruction packet"); |
666 | 42 | else if (HexagonShuffler::SHUFFLE_ERROR_STORES == Erm) |
667 | 0 | Error(IDLoc, "invalid instruction packet: too many stores"); |
668 | 42 | else if (HexagonShuffler::SHUFFLE_ERROR_LOADS == Erm) |
669 | 0 | Error(IDLoc, "invalid instruction packet: too many loads"); |
670 | 42 | else if (HexagonShuffler::SHUFFLE_ERROR_BRANCHES == Erm) |
671 | 13 | Error(IDLoc, "too many branches in packet"); |
672 | 29 | else if (HexagonShuffler::SHUFFLE_ERROR_NOSLOTS == Erm) |
673 | 0 | Error(IDLoc, "invalid instruction packet: out of slots"); |
674 | 29 | else if (HexagonShuffler::SHUFFLE_ERROR_SLOTS == Erm) |
675 | 29 | Error(IDLoc, "invalid instruction packet: slot error"); |
676 | 0 | else if (HexagonShuffler::SHUFFLE_ERROR_ERRATA2 == Erm) |
677 | 0 | Error(IDLoc, "v60 packet violation"); |
678 | 0 | else if (HexagonShuffler::SHUFFLE_ERROR_STORE_LOAD_CONFLICT == Erm) |
679 | 0 | Error(IDLoc, "slot 0 instruction does not allow slot 1 store"); |
680 | 0 | else |
681 | 0 | Error(IDLoc, "unknown error in instruction packet"); |
682 | 42 | } |
683 | 411 | } |
684 | | |
685 | 411 | unsigned Warn = Check.getWarning(); |
686 | 411 | if (Warn != HexagonMCErrInfo::CHECK_SUCCESS) { |
687 | 0 | if (HexagonMCErrInfo::CHECK_WARN_CURRENT & Warn) |
688 | 0 | Warning(IDLoc, "register `" + R + "' used with `.cur' " |
689 | 0 | "but not used in the same packet"); |
690 | 0 | else if (HexagonMCErrInfo::CHECK_WARN_TEMPORARY & Warn) |
691 | 0 | Warning(IDLoc, "register `" + R + "' used with `.tmp' " |
692 | 0 | "but not used in the same packet"); |
693 | 0 | } |
694 | 411 | } |
695 | | |
696 | 3.25k | if (CheckOk) { |
697 | 2.94k | MCB.setLoc(IDLoc); |
698 | 2.94k | if (HexagonMCInstrInfo::bundleSize(MCB) == 0) { |
699 | 40 | assert(!HexagonMCInstrInfo::isInnerLoop(MCB)); |
700 | 40 | assert(!HexagonMCInstrInfo::isOuterLoop(MCB)); |
701 | | // Empty packets are valid yet aren't emitted |
702 | 40 | return false; |
703 | 40 | } |
704 | 2.90k | Out.EmitInstruction(MCB, getSTI(), KsError); |
705 | 2.90k | if (KsError) { |
706 | 4 | return true; |
707 | 4 | } |
708 | 2.90k | } else { |
709 | | // If compounding and duplexing didn't reduce the size below |
710 | | // 4 or less we have a packet that is too big. |
711 | 313 | if (HexagonMCInstrInfo::bundleSize(MCB) > HEXAGON_PACKET_SIZE) { |
712 | 41 | Error(IDLoc, "invalid instruction packet: out of slots"); |
713 | 41 | return true; // Error |
714 | 41 | } |
715 | 313 | } |
716 | | |
717 | 3.17k | return false; // No error |
718 | 3.25k | } |
719 | | |
720 | 768 | bool HexagonAsmParser::matchBundleOptions() { |
721 | 768 | MCAsmParser &Parser = getParser(); |
722 | 768 | MCAsmLexer &Lexer = getLexer(); |
723 | 768 | while (true) { |
724 | 768 | if (!Parser.getTok().is(AsmToken::Colon)) |
725 | 768 | return false; |
726 | 0 | Lexer.Lex(); |
727 | 0 | StringRef Option = Parser.getTok().getString(); |
728 | 0 | if (Option.compare_lower("endloop0") == 0) |
729 | 0 | HexagonMCInstrInfo::setInnerLoop(MCB); |
730 | 0 | else if (Option.compare_lower("endloop1") == 0) |
731 | 0 | HexagonMCInstrInfo::setOuterLoop(MCB); |
732 | 0 | else if (Option.compare_lower("mem_noshuf") == 0) |
733 | 0 | HexagonMCInstrInfo::setMemReorderDisabled(MCB); |
734 | 0 | else if (Option.compare_lower("mem_shuf") == 0) |
735 | 0 | HexagonMCInstrInfo::setMemStoreReorderEnabled(MCB); |
736 | 0 | else |
737 | 0 | return true; |
738 | 0 | Lexer.Lex(); |
739 | 0 | } |
740 | 768 | } |
741 | | |
742 | | // For instruction aliases, immediates are generated rather than |
743 | | // MCConstantExpr. Convert them for uniform MCExpr. |
744 | | // Also check for signed/unsigned mismatches and warn |
745 | 5.26k | void HexagonAsmParser::canonicalizeImmediates(MCInst &MCI) { |
746 | 5.26k | MCInst NewInst; |
747 | 5.26k | NewInst.setOpcode(MCI.getOpcode()); |
748 | 5.26k | for (MCOperand &I : MCI) |
749 | 7.54k | if (I.isImm()) { |
750 | 3 | int64_t Value (I.getImm()); |
751 | 3 | if ((Value & 0x100000000) != (Value & 0x80000000)) { |
752 | | // Detect flipped bit 33 wrt bit 32 and signal warning |
753 | 3 | Value ^= 0x100000000; |
754 | 3 | if (WarnSignedMismatch) |
755 | 3 | Warning (MCI.getLoc(), "Signed/Unsigned mismatch"); |
756 | 3 | } |
757 | 3 | NewInst.addOperand(MCOperand::createExpr( |
758 | 3 | MCConstantExpr::create(Value, getContext()))); |
759 | 3 | } |
760 | 7.54k | else |
761 | 7.54k | NewInst.addOperand(I); |
762 | 5.26k | MCI = NewInst; |
763 | 5.26k | } |
764 | | |
765 | | bool HexagonAsmParser::matchOneInstruction(MCInst &MCI, SMLoc IDLoc, |
766 | | OperandVector &InstOperands, |
767 | | uint64_t &ErrorInfo, |
768 | | bool MatchingInlineAsm, |
769 | | bool &MustExtend, unsigned int &ErrorCode) |
770 | 6.42k | { |
771 | | // Perform matching with tablegen asmmatcher generated function |
772 | 6.42k | int result = |
773 | 6.42k | MatchInstructionImpl(InstOperands, MCI, ErrorInfo, MatchingInlineAsm); |
774 | 6.42k | if (result == Match_Success) { |
775 | 5.26k | MCI.setLoc(IDLoc); |
776 | 5.26k | MustExtend = mustExtend(InstOperands); |
777 | 5.26k | canonicalizeImmediates(MCI); |
778 | 5.26k | result = processInstruction(MCI, InstOperands, IDLoc, MustExtend); |
779 | | |
780 | 5.26k | DEBUG(dbgs() << "Insn:"); |
781 | 5.26k | DEBUG(MCI.dump_pretty(dbgs())); |
782 | 5.26k | DEBUG(dbgs() << "\n\n"); |
783 | | |
784 | 5.26k | MCI.setLoc(IDLoc); |
785 | 5.26k | } |
786 | | |
787 | | // Create instruction operand for bundle instruction |
788 | | // Break this into a separate function Code here is less readable |
789 | | // Think about how to get an instruction error to report correctly. |
790 | | // SMLoc will return the "{" |
791 | 6.42k | switch (result) { |
792 | 0 | default: |
793 | 0 | break; |
794 | 5.26k | case Match_Success: |
795 | 5.26k | return false; |
796 | 0 | case Match_MissingFeature: |
797 | | // return Error(IDLoc, "invalid instruction"); |
798 | 0 | ErrorCode = KS_ERR_ASM_HEXAGON_MISSINGFEATURE; |
799 | 0 | return true; |
800 | 532 | case Match_MnemonicFail: |
801 | | // return Error(IDLoc, "unrecognized instruction"); |
802 | 532 | ErrorCode = KS_ERR_ASM_HEXAGON_MNEMONICFAIL; |
803 | 532 | return true; |
804 | 634 | case Match_InvalidOperand: |
805 | | #if 0 |
806 | | SMLoc ErrorLoc = IDLoc; |
807 | | if (ErrorInfo != ~0U) { |
808 | | if (ErrorInfo >= InstOperands.size()) { |
809 | | // return Error(IDLoc, "too few operands for instruction"); |
810 | | } |
811 | | |
812 | | ErrorLoc = (static_cast<HexagonOperand *>(InstOperands[ErrorInfo].get())) |
813 | | ->getStartLoc(); |
814 | | if (ErrorLoc == SMLoc()) |
815 | | ErrorLoc = IDLoc; |
816 | | } |
817 | | #endif |
818 | | // return Error(ErrorLoc, "invalid operand for instruction"); |
819 | 634 | ErrorCode = KS_ERR_ASM_HEXAGON_INVALIDOPERAND; |
820 | 634 | return true; |
821 | 6.42k | } |
822 | 6.42k | llvm_unreachable("Implement any new match types added!"); |
823 | 6.42k | } |
824 | | |
825 | 5.26k | bool HexagonAsmParser::mustExtend(OperandVector &Operands) { |
826 | 5.26k | unsigned Count = 0; |
827 | 5.26k | for (std::unique_ptr<MCParsedAsmOperand> &i : Operands) |
828 | 14.8k | if (i->isImm()) |
829 | 3.97k | if (static_cast<HexagonOperand *>(i.get())->Imm.MustExtend) |
830 | 2.03k | ++Count; |
831 | | // Multiple extenders should have been filtered by iss9Ext et. al. |
832 | 5.26k | assert(Count < 2 && "Multiple extenders"); |
833 | 5.26k | return Count == 1; |
834 | 5.26k | } |
835 | | |
836 | | bool HexagonAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
837 | | OperandVector &Operands, |
838 | | MCStreamer &Out, |
839 | | uint64_t &ErrorInfo, |
840 | | bool MatchingInlineAsm, unsigned int &ErrorCode, uint64_t &Address) |
841 | 8.07k | { |
842 | 8.07k | if (!InBrackets) { |
843 | 4.51k | MCB.clear(); |
844 | 4.51k | MCB.addOperand(MCOperand::createImm(0)); |
845 | 4.51k | } |
846 | 8.07k | if (Operands.size() == 0) { |
847 | 46 | ErrorCode = KS_ERR_ASM_INVALIDOPERAND; |
848 | 46 | return true; |
849 | 46 | } |
850 | 8.03k | HexagonOperand &FirstOperand = static_cast<HexagonOperand &>(*Operands[0]); |
851 | 8.03k | if (FirstOperand.isToken() && FirstOperand.getToken() == "{") { |
852 | 833 | assert(Operands.size() == 1 && "Brackets should be by themselves"); |
853 | 833 | if (InBrackets) { |
854 | | //getParser().Error(IDLoc, "Already in a packet"); |
855 | 0 | ErrorCode = KS_ERR_ASM_INVALIDOPERAND; |
856 | 0 | return true; |
857 | 0 | } |
858 | 833 | InBrackets = true; |
859 | 833 | return false; |
860 | 833 | } |
861 | 7.20k | if (FirstOperand.isToken() && FirstOperand.getToken() == "}") { |
862 | 773 | assert(Operands.size() == 1 && "Brackets should be by themselves"); |
863 | 773 | if (!InBrackets) { |
864 | | //getParser().Error(IDLoc, "Not in a packet"); |
865 | 5 | ErrorCode = KS_ERR_ASM_INVALIDOPERAND; |
866 | 5 | return true; |
867 | 5 | } |
868 | 768 | InBrackets = false; |
869 | 768 | if (matchBundleOptions()) { |
870 | 0 | ErrorCode = KS_ERR_ASM_INVALIDOPERAND; |
871 | 0 | return true; |
872 | 0 | } |
873 | 768 | return finishBundle(IDLoc, Out, ErrorCode); |
874 | 768 | } |
875 | 6.42k | MCInst *SubInst = new (getParser().getContext()) MCInst; |
876 | 6.42k | bool MustExtend = false; |
877 | 6.42k | if (matchOneInstruction(*SubInst, IDLoc, Operands, ErrorInfo, |
878 | 6.42k | MatchingInlineAsm, MustExtend, ErrorCode)) { |
879 | 1.16k | ErrorCode = KS_ERR_ASM_INVALIDOPERAND; |
880 | 1.16k | return true; |
881 | 1.16k | } |
882 | 5.26k | HexagonMCInstrInfo::extendIfNeeded( |
883 | 5.26k | getParser().getContext(), MCII, MCB, *SubInst, |
884 | 5.26k | HexagonMCInstrInfo::isExtended(MCII, *SubInst) || MustExtend); |
885 | 5.26k | MCB.addOperand(MCOperand::createInst(SubInst)); |
886 | 5.26k | if (!InBrackets) |
887 | 2.49k | return finishBundle(IDLoc, Out, ErrorCode); |
888 | 2.77k | return false; |
889 | 5.26k | } |
890 | | |
891 | | /// ParseDirective parses the Hexagon specific directives |
892 | 64.1k | bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) { |
893 | 64.1k | StringRef IDVal = DirectiveID.getIdentifier(); |
894 | 64.1k | if ((IDVal.lower() == ".word") || (IDVal.lower() == ".4byte")) |
895 | 4.73k | return ParseDirectiveValue(4, DirectiveID.getLoc()); |
896 | 59.4k | if (IDVal.lower() == ".short" || IDVal.lower() == ".hword" || |
897 | 59.4k | IDVal.lower() == ".half") |
898 | 24 | return ParseDirectiveValue(2, DirectiveID.getLoc()); |
899 | 59.4k | if (IDVal.lower() == ".falign") |
900 | 0 | return ParseDirectiveFalign(256, DirectiveID.getLoc()); |
901 | 59.4k | if ((IDVal.lower() == ".lcomm") || (IDVal.lower() == ".lcommon")) |
902 | 89 | return ParseDirectiveComm(true, DirectiveID.getLoc()); |
903 | 59.3k | if ((IDVal.lower() == ".comm") || (IDVal.lower() == ".common")) |
904 | 1.64k | return ParseDirectiveComm(false, DirectiveID.getLoc()); |
905 | 57.6k | if (IDVal.lower() == ".subsection") |
906 | 0 | return ParseDirectiveSubsection(DirectiveID.getLoc()); |
907 | | |
908 | 57.6k | return true; |
909 | 57.6k | } |
910 | 0 | bool HexagonAsmParser::ParseDirectiveSubsection(SMLoc L) { |
911 | 0 | const MCExpr *Subsection = 0; |
912 | 0 | int64_t Res; |
913 | |
|
914 | 0 | assert((getLexer().isNot(AsmToken::EndOfStatement)) && |
915 | 0 | "Invalid subsection directive"); |
916 | 0 | getParser().parseExpression(Subsection); |
917 | |
|
918 | 0 | if (!Subsection->evaluateAsAbsolute(Res)) |
919 | 0 | return Error(L, "Cannot evaluate subsection number"); |
920 | | |
921 | 0 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
922 | 0 | return TokError("unexpected token in directive"); |
923 | | |
924 | | // 0-8192 is the hard-coded range in MCObjectStreamper.cpp, this keeps the |
925 | | // negative subsections together and in the same order but at the opposite |
926 | | // end of the section. Only legacy hexagon-gcc created assembly code |
927 | | // used negative subsections. |
928 | 0 | if ((Res < 0) && (Res > -8193)) |
929 | 0 | Subsection = MCConstantExpr::create(8192 + Res, this->getContext()); |
930 | |
|
931 | 0 | getStreamer().SubSection(Subsection); |
932 | 0 | return false; |
933 | 0 | } |
934 | | |
935 | | /// ::= .falign [expression] |
936 | 0 | bool HexagonAsmParser::ParseDirectiveFalign(unsigned Size, SMLoc L) { |
937 | |
|
938 | 0 | int64_t MaxBytesToFill = 15; |
939 | | |
940 | | // if there is an arguement |
941 | 0 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
942 | 0 | const MCExpr *Value; |
943 | 0 | SMLoc ExprLoc = L; |
944 | | |
945 | | // Make sure we have a number (false is returned if expression is a number) |
946 | 0 | if (getParser().parseExpression(Value) == false) { |
947 | | // Make sure this is a number that is in range |
948 | 0 | const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); |
949 | 0 | uint64_t IntValue = MCE->getValue(); |
950 | 0 | if (!isUIntN(Size, IntValue) && !isIntN(Size, IntValue)) |
951 | 0 | return Error(ExprLoc, "literal value out of range (256) for falign"); |
952 | 0 | MaxBytesToFill = IntValue; |
953 | 0 | Lex(); |
954 | 0 | } else { |
955 | 0 | return Error(ExprLoc, "not a valid expression for falign directive"); |
956 | 0 | } |
957 | 0 | } |
958 | | |
959 | 0 | getTargetStreamer().emitFAlign(16, MaxBytesToFill); |
960 | 0 | Lex(); |
961 | |
|
962 | 0 | return false; |
963 | 0 | } |
964 | | |
965 | | /// ::= .word [ expression (, expression)* ] |
966 | | bool HexagonAsmParser::ParseDirectiveValue(unsigned Size, SMLoc L) |
967 | 4.75k | { |
968 | 4.75k | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
969 | | |
970 | 14.2k | for (;;) { |
971 | 14.2k | const MCExpr *Value; |
972 | | //SMLoc ExprLoc = L; |
973 | 14.2k | if (getParser().parseExpression(Value)) |
974 | 724 | return true; |
975 | | |
976 | | // Special case constant expressions to match code generator. |
977 | 13.5k | if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { |
978 | 2.43k | bool Error; |
979 | | //assert(Size <= 8 && "Invalid size"); |
980 | 2.43k | if (Size > 8) |
981 | 0 | return true; |
982 | 2.43k | uint64_t IntValue = MCE->getValue(); |
983 | 2.43k | if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) |
984 | | //return Error(ExprLoc, "literal value out of range for directive"); |
985 | 2 | return true; |
986 | 2.42k | getStreamer().EmitIntValue(IntValue, Size, Error); |
987 | 2.42k | if (Error) { |
988 | 0 | return true; |
989 | 0 | } |
990 | 2.42k | } else |
991 | 11.1k | getStreamer().EmitValue(Value, Size); |
992 | | |
993 | 13.5k | if (getLexer().is(AsmToken::EndOfStatement)) |
994 | 3.39k | break; |
995 | | |
996 | | // FIXME: Improve diagnostic. |
997 | 10.1k | if (getLexer().isNot(AsmToken::Comma)) |
998 | | //return TokError("unexpected token in directive"); |
999 | 604 | return true; |
1000 | 9.55k | Lex(); |
1001 | 9.55k | } |
1002 | 4.72k | } |
1003 | | |
1004 | 3.42k | Lex(); |
1005 | 3.42k | return false; |
1006 | 4.75k | } |
1007 | | |
1008 | | // This is largely a copy of AsmParser's ParseDirectiveComm extended to |
1009 | | // accept a 3rd argument, AccessAlignment which indicates the smallest |
1010 | | // memory access made to the symbol, expressed in bytes. If no |
1011 | | // AccessAlignment is specified it defaults to the Alignment Value. |
1012 | | // Hexagon's .lcomm: |
1013 | | // .lcomm Symbol, Length, Alignment, AccessAlignment |
1014 | 1.73k | bool HexagonAsmParser::ParseDirectiveComm(bool IsLocal, SMLoc Loc) { |
1015 | | // FIXME: need better way to detect if AsmStreamer (upstream removed |
1016 | | // getKind()) |
1017 | 1.73k | if (getStreamer().hasRawTextSupport()) |
1018 | 0 | return true; // Only object file output requires special treatment. |
1019 | | |
1020 | 1.73k | StringRef Name; |
1021 | 1.73k | if (getParser().parseIdentifier(Name)) |
1022 | 731 | return TokError("expected identifier in directive"); |
1023 | | // Handle the identifier as the key symbol. |
1024 | 1.00k | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); |
1025 | | |
1026 | 1.00k | if (getLexer().isNot(AsmToken::Comma)) |
1027 | 30 | return TokError("unexpected token in directive"); |
1028 | 972 | Lex(); |
1029 | | |
1030 | 972 | int64_t Size; |
1031 | 972 | SMLoc SizeLoc = getLexer().getLoc(); |
1032 | 972 | if (getParser().parseAbsoluteExpression(Size)) |
1033 | 181 | return true; |
1034 | | |
1035 | 791 | int64_t ByteAlignment = 1; |
1036 | 791 | SMLoc ByteAlignmentLoc; |
1037 | 791 | if (getLexer().is(AsmToken::Comma)) { |
1038 | 108 | Lex(); |
1039 | 108 | ByteAlignmentLoc = getLexer().getLoc(); |
1040 | 108 | if (getParser().parseAbsoluteExpression(ByteAlignment)) |
1041 | 0 | return true; |
1042 | 108 | if (!isPowerOf2_64(ByteAlignment)) |
1043 | 108 | return Error(ByteAlignmentLoc, "alignment must be a power of 2"); |
1044 | 108 | } |
1045 | | |
1046 | 683 | int64_t AccessAlignment = 0; |
1047 | 683 | if (getLexer().is(AsmToken::Comma)) { |
1048 | | // The optional access argument specifies the size of the smallest memory |
1049 | | // access to be made to the symbol, expressed in bytes. |
1050 | 0 | SMLoc AccessAlignmentLoc; |
1051 | 0 | Lex(); |
1052 | 0 | AccessAlignmentLoc = getLexer().getLoc(); |
1053 | 0 | if (getParser().parseAbsoluteExpression(AccessAlignment)) |
1054 | 0 | return true; |
1055 | | |
1056 | 0 | if (!isPowerOf2_64(AccessAlignment)) |
1057 | 0 | return Error(AccessAlignmentLoc, "access alignment must be a power of 2"); |
1058 | 0 | } |
1059 | | |
1060 | 683 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
1061 | 6 | return TokError("unexpected token in '.comm' or '.lcomm' directive"); |
1062 | | |
1063 | 677 | Lex(); |
1064 | | |
1065 | | // NOTE: a size of zero for a .comm should create a undefined symbol |
1066 | | // but a size of .lcomm creates a bss symbol of size zero. |
1067 | 677 | if (Size < 0) |
1068 | 9 | return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " |
1069 | 9 | "be less than zero"); |
1070 | | |
1071 | | // NOTE: The alignment in the directive is a power of 2 value, the assembler |
1072 | | // may internally end up wanting an alignment in bytes. |
1073 | | // FIXME: Diagnose overflow. |
1074 | 668 | if (ByteAlignment < 0) |
1075 | 0 | return Error(ByteAlignmentLoc, "invalid '.comm' or '.lcomm' directive " |
1076 | 0 | "alignment, can't be less than zero"); |
1077 | | |
1078 | 668 | if (!Sym->isUndefined()) |
1079 | 0 | return Error(Loc, "invalid symbol redefinition"); |
1080 | | |
1081 | | #if 0 |
1082 | | HexagonMCELFStreamer &HexagonELFStreamer = |
1083 | | static_cast<HexagonMCELFStreamer &>(getStreamer()); |
1084 | | if (IsLocal) { |
1085 | | HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol(Sym, Size, ByteAlignment, |
1086 | | AccessAlignment); |
1087 | | return false; |
1088 | | } |
1089 | | |
1090 | | HexagonELFStreamer.HexagonMCEmitCommonSymbol(Sym, Size, ByteAlignment, |
1091 | | AccessAlignment); |
1092 | | #endif |
1093 | 668 | return false; |
1094 | 668 | } |
1095 | | |
1096 | | // validate register against architecture |
1097 | 17.0k | bool HexagonAsmParser::RegisterMatchesArch(unsigned MatchNum) const { |
1098 | 17.0k | return true; |
1099 | 17.0k | } |
1100 | | |
1101 | | // extern "C" void LLVMInitializeHexagonAsmLexer(); |
1102 | | |
1103 | | /// Force static initialization. |
1104 | 25 | extern "C" void LLVMInitializeHexagonAsmParser() { |
1105 | 25 | RegisterMCAsmParser<HexagonAsmParser> X(TheHexagonTarget); |
1106 | 25 | } |
1107 | | |
1108 | | #define GET_MATCHER_IMPLEMENTATION |
1109 | | #define GET_REGISTER_MATCHER |
1110 | | #include "HexagonGenAsmMatcher.inc" |
1111 | | |
1112 | | namespace { |
1113 | 2.99M | bool previousEqual(OperandVector &Operands, size_t Index, StringRef String) { |
1114 | 2.99M | if (Index >= Operands.size()) |
1115 | 169k | return false; |
1116 | 2.82M | MCParsedAsmOperand &Operand = *Operands[Operands.size() - Index - 1]; |
1117 | 2.82M | if (!Operand.isToken()) |
1118 | 330k | return false; |
1119 | 2.49M | return static_cast<HexagonOperand &>(Operand).getToken().equals_lower(String); |
1120 | 2.82M | } |
1121 | 4.77k | bool previousIsLoop(OperandVector &Operands, size_t Index) { |
1122 | 4.77k | return previousEqual(Operands, Index, "loop0") || |
1123 | 4.77k | previousEqual(Operands, Index, "loop1") || |
1124 | 4.77k | previousEqual(Operands, Index, "sp1loop0") || |
1125 | 4.77k | previousEqual(Operands, Index, "sp2loop0") || |
1126 | 4.77k | previousEqual(Operands, Index, "sp3loop0"); |
1127 | 4.77k | } |
1128 | | } |
1129 | | |
1130 | 673k | bool HexagonAsmParser::splitIdentifier(OperandVector &Operands) { |
1131 | 673k | AsmToken const &Token = getParser().getTok(); |
1132 | 673k | StringRef String = Token.getString(); |
1133 | 673k | SMLoc Loc = Token.getLoc(); |
1134 | 673k | getLexer().Lex(); |
1135 | 715k | do { |
1136 | 715k | std::pair<StringRef, StringRef> HeadTail = String.split('.'); |
1137 | 715k | if (!HeadTail.first.empty()) |
1138 | 364k | Operands.push_back(HexagonOperand::CreateToken(HeadTail.first, Loc)); |
1139 | 715k | if (!HeadTail.second.empty()) |
1140 | 42.0k | Operands.push_back(HexagonOperand::CreateToken( |
1141 | 42.0k | String.substr(HeadTail.first.size(), 1), Loc)); |
1142 | 715k | String = HeadTail.second; |
1143 | 715k | } while (!String.empty()); |
1144 | 673k | return false; |
1145 | 673k | } |
1146 | | |
1147 | 690k | bool HexagonAsmParser::parseOperand(OperandVector &Operands) { |
1148 | 690k | unsigned Register; |
1149 | 690k | SMLoc Begin; |
1150 | 690k | SMLoc End; |
1151 | 690k | unsigned int ErrorCode; |
1152 | 690k | MCAsmLexer &Lexer = getLexer(); |
1153 | 690k | if (!ParseRegister(Register, Begin, End, ErrorCode)) { |
1154 | 17.0k | if (!ErrorMissingParenthesis) |
1155 | 17.0k | switch (Register) { |
1156 | 11.2k | default: |
1157 | 11.2k | break; |
1158 | 11.2k | case Hexagon::P0: |
1159 | 3.67k | case Hexagon::P1: |
1160 | 5.76k | case Hexagon::P2: |
1161 | 5.81k | case Hexagon::P3: |
1162 | 5.81k | if (previousEqual(Operands, 0, "if")) { |
1163 | 645 | if (WarnMissingParenthesis) |
1164 | 645 | Warning (Begin, "Missing parenthesis around predicate register"); |
1165 | 645 | static char const *LParen = "("; |
1166 | 645 | static char const *RParen = ")"; |
1167 | 645 | Operands.push_back(HexagonOperand::CreateToken(LParen, Begin)); |
1168 | 645 | Operands.push_back(HexagonOperand::CreateReg(Register, Begin, End)); |
1169 | 645 | AsmToken MaybeDotNew = Lexer.getTok(); |
1170 | 645 | if (MaybeDotNew.is(AsmToken::TokenKind::Identifier) && |
1171 | 645 | MaybeDotNew.getString().equals_lower(".new")) |
1172 | 0 | splitIdentifier(Operands); |
1173 | 645 | Operands.push_back(HexagonOperand::CreateToken(RParen, Begin)); |
1174 | 645 | return false; |
1175 | 645 | } |
1176 | 5.17k | if (previousEqual(Operands, 0, "!") && |
1177 | 5.17k | previousEqual(Operands, 1, "if")) { |
1178 | 1.11k | if (WarnMissingParenthesis) |
1179 | 1.11k | Warning (Begin, "Missing parenthesis around predicate register"); |
1180 | 1.11k | static char const *LParen = "("; |
1181 | 1.11k | static char const *RParen = ")"; |
1182 | 1.11k | Operands.insert(Operands.end () - 1, |
1183 | 1.11k | HexagonOperand::CreateToken(LParen, Begin)); |
1184 | 1.11k | Operands.push_back(HexagonOperand::CreateReg(Register, Begin, End)); |
1185 | 1.11k | AsmToken MaybeDotNew = Lexer.getTok(); |
1186 | 1.11k | if (MaybeDotNew.is(AsmToken::TokenKind::Identifier) && |
1187 | 1.11k | MaybeDotNew.getString().equals_lower(".new")) |
1188 | 0 | splitIdentifier(Operands); |
1189 | 1.11k | Operands.push_back(HexagonOperand::CreateToken(RParen, Begin)); |
1190 | 1.11k | return false; |
1191 | 1.11k | } |
1192 | 4.05k | break; |
1193 | 17.0k | } |
1194 | 15.2k | Operands.push_back(HexagonOperand::CreateReg( |
1195 | 15.2k | Register, Begin, End)); |
1196 | 15.2k | return false; |
1197 | 17.0k | } |
1198 | 673k | return splitIdentifier(Operands); |
1199 | 690k | } |
1200 | | |
1201 | 296 | bool HexagonAsmParser::isLabel(AsmToken &Token, bool &valid) { |
1202 | 296 | valid = true; |
1203 | 296 | MCAsmLexer &Lexer = getLexer(); |
1204 | 296 | AsmToken const &Second = Lexer.getTok(); |
1205 | 296 | AsmToken Third = Lexer.peekTok(); |
1206 | 296 | if (Third.is(AsmToken::Error)) { |
1207 | 0 | valid = false; |
1208 | 0 | return true; |
1209 | 0 | } |
1210 | 296 | StringRef String = Token.getString(); |
1211 | 296 | if (Token.is(AsmToken::TokenKind::LCurly) || |
1212 | 296 | Token.is(AsmToken::TokenKind::RCurly)) |
1213 | 0 | return false; |
1214 | 296 | if (!Token.is(AsmToken::TokenKind::Identifier)) |
1215 | 147 | return true; |
1216 | 149 | if (!MatchRegisterName(String.lower())) |
1217 | 87 | return true; |
1218 | 62 | (void)Second; |
1219 | 62 | assert(Second.is(AsmToken::Colon)); |
1220 | 62 | StringRef Raw (String.data(), Third.getString().data() - String.data() + |
1221 | 62 | Third.getString().size()); |
1222 | 62 | std::string Collapsed = Raw; |
1223 | 62 | Collapsed.erase(std::remove_if(Collapsed.begin(), Collapsed.end(), isspace), |
1224 | 62 | Collapsed.end()); |
1225 | 62 | StringRef Whole = Collapsed; |
1226 | 62 | std::pair<StringRef, StringRef> DotSplit = Whole.split('.'); |
1227 | 62 | if (!MatchRegisterName(DotSplit.first.lower())) |
1228 | 23 | return true; |
1229 | 39 | return false; |
1230 | 62 | } |
1231 | | |
1232 | 17.0k | bool HexagonAsmParser::handleNoncontigiousRegister(bool Contigious, SMLoc &Loc) { |
1233 | 17.0k | if (!Contigious && ErrorNoncontigiousRegister) { |
1234 | 0 | Error(Loc, "Register name is not contiguous"); |
1235 | 0 | return true; |
1236 | 0 | } |
1237 | 17.0k | if (!Contigious && WarnNoncontigiousRegister) |
1238 | 245 | Warning(Loc, "Register name is not contiguous"); |
1239 | 17.0k | return false; |
1240 | 17.0k | } |
1241 | | |
1242 | 690k | bool HexagonAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, unsigned int &ErrorCode) { |
1243 | 690k | MCAsmLexer &Lexer = getLexer(); |
1244 | 690k | StartLoc = getLexer().getLoc(); |
1245 | 690k | SmallVector<AsmToken, 5> Lookahead; |
1246 | 690k | StringRef RawString(Lexer.getTok().getString().data(), 0); |
1247 | 690k | bool Again = Lexer.is(AsmToken::Identifier); |
1248 | 690k | bool NeededWorkaround = false; |
1249 | 858k | while (Again) { |
1250 | 167k | AsmToken const &Token = Lexer.getTok(); |
1251 | 167k | RawString = StringRef(RawString.data(), |
1252 | 167k | Token.getString().data() - RawString.data () + |
1253 | 167k | Token.getString().size()); |
1254 | 167k | Lookahead.push_back(Token); |
1255 | 167k | Lexer.Lex(); |
1256 | 167k | bool Contigious = Lexer.getTok().getString().data() == |
1257 | 167k | Lookahead.back().getString().data() + |
1258 | 167k | Lookahead.back().getString().size(); |
1259 | 167k | bool Type = Lexer.is(AsmToken::Identifier) || Lexer.is(AsmToken::Dot) || |
1260 | 167k | Lexer.is(AsmToken::Integer) || Lexer.is(AsmToken::Real) || |
1261 | 167k | Lexer.is(AsmToken::Colon); |
1262 | 167k | bool Workaround = Lexer.is(AsmToken::Colon) || |
1263 | 167k | Lookahead.back().is(AsmToken::Colon); |
1264 | 167k | Again = (Contigious && Type) || (Workaround && Type); |
1265 | 167k | NeededWorkaround = NeededWorkaround || (Again && !(Contigious && Type)); |
1266 | 167k | } |
1267 | 690k | std::string Collapsed = RawString; |
1268 | 690k | Collapsed.erase(std::remove_if(Collapsed.begin(), Collapsed.end(), isspace), |
1269 | 690k | Collapsed.end()); |
1270 | 690k | StringRef FullString = Collapsed; |
1271 | 690k | std::pair<StringRef, StringRef> DotSplit = FullString.split('.'); |
1272 | 690k | unsigned DotReg = MatchRegisterName(DotSplit.first.lower()); |
1273 | 690k | if (DotReg != Hexagon::NoRegister && RegisterMatchesArch(DotReg)) { |
1274 | 15.9k | if (DotSplit.second.empty()) { |
1275 | 14.4k | RegNo = DotReg; |
1276 | 14.4k | EndLoc = Lexer.getLoc(); |
1277 | 14.4k | if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc)) |
1278 | 0 | return true; |
1279 | 14.4k | return false; |
1280 | 14.4k | } else { |
1281 | 1.55k | RegNo = DotReg; |
1282 | 1.55k | size_t First = RawString.find('.'); |
1283 | 1.55k | StringRef DotString (RawString.data() + First, RawString.size() - First); |
1284 | 1.55k | Lexer.UnLex(AsmToken(AsmToken::Identifier, DotString)); |
1285 | 1.55k | EndLoc = Lexer.getLoc(); |
1286 | 1.55k | if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc)) |
1287 | 0 | return true; |
1288 | 1.55k | return false; |
1289 | 1.55k | } |
1290 | 15.9k | } |
1291 | 674k | std::pair<StringRef, StringRef> ColonSplit = StringRef(FullString).split(':'); |
1292 | 674k | unsigned ColonReg = MatchRegisterName(ColonSplit.first.lower()); |
1293 | 674k | if (ColonReg != Hexagon::NoRegister && RegisterMatchesArch(DotReg)) { |
1294 | 1.04k | Lexer.UnLex(Lookahead.back()); |
1295 | 1.04k | Lookahead.pop_back(); |
1296 | 1.04k | Lexer.UnLex(Lookahead.back()); |
1297 | 1.04k | Lookahead.pop_back(); |
1298 | 1.04k | RegNo = ColonReg; |
1299 | 1.04k | EndLoc = Lexer.getLoc(); |
1300 | 1.04k | if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc)) |
1301 | 0 | return true; |
1302 | 1.04k | return false; |
1303 | 1.04k | } |
1304 | 820k | while (!Lookahead.empty()) { |
1305 | 146k | Lexer.UnLex(Lookahead.back()); |
1306 | 146k | Lookahead.pop_back(); |
1307 | 146k | } |
1308 | 673k | return true; |
1309 | 674k | } |
1310 | | |
1311 | 735k | bool HexagonAsmParser::implicitExpressionLocation(OperandVector &Operands) { |
1312 | 735k | if (previousEqual(Operands, 0, "call")) |
1313 | 357 | return true; |
1314 | 735k | if (previousEqual(Operands, 0, "jump")) |
1315 | 1.76k | if (!getLexer().getTok().is(AsmToken::Colon)) |
1316 | 1.66k | return true; |
1317 | 733k | if (previousEqual(Operands, 0, "(") && previousIsLoop(Operands, 1)) |
1318 | 24 | return true; |
1319 | 733k | if (previousEqual(Operands, 1, ":") && previousEqual(Operands, 2, "jump") && |
1320 | 733k | (previousEqual(Operands, 0, "nt") || previousEqual(Operands, 0, "t"))) |
1321 | 72 | return true; |
1322 | 733k | return false; |
1323 | 733k | } |
1324 | | |
1325 | 44.5k | bool HexagonAsmParser::parseExpression(MCExpr const *& Expr) { |
1326 | 44.5k | llvm_ks::SmallVector<AsmToken, 4> Tokens; |
1327 | 44.5k | MCAsmLexer &Lexer = getLexer(); |
1328 | 44.5k | bool Done = false; |
1329 | 44.5k | static char const * Comma = ","; |
1330 | 2.73M | do { |
1331 | 2.73M | Tokens.emplace_back (Lexer.getTok()); |
1332 | 2.73M | Lexer.Lex(); |
1333 | 2.73M | switch (Tokens.back().getKind()) |
1334 | 2.73M | { |
1335 | 315k | case AsmToken::TokenKind::Hash: |
1336 | 315k | if (Tokens.size () > 1) |
1337 | 315k | if ((Tokens.end () - 2)->getKind() == AsmToken::TokenKind::Plus) { |
1338 | 407 | Tokens.insert(Tokens.end() - 2, |
1339 | 407 | AsmToken(AsmToken::TokenKind::Comma, Comma)); |
1340 | 407 | Done = true; |
1341 | 407 | } |
1342 | 315k | break; |
1343 | 870 | case AsmToken::TokenKind::RCurly: |
1344 | 43.9k | case AsmToken::TokenKind::EndOfStatement: |
1345 | 44.1k | case AsmToken::TokenKind::Eof: |
1346 | 44.1k | Done = true; |
1347 | 44.1k | break; |
1348 | 2.37M | default: |
1349 | 2.37M | break; |
1350 | 2.73M | } |
1351 | 2.73M | } while (!Done); |
1352 | 2.77M | while (!Tokens.empty()) { |
1353 | 2.73M | Lexer.UnLex(Tokens.back()); |
1354 | 2.73M | Tokens.pop_back(); |
1355 | 2.73M | } |
1356 | 44.5k | return getParser().parseExpression(Expr); |
1357 | 44.5k | } |
1358 | | |
1359 | 692k | bool HexagonAsmParser::parseExpressionOrOperand(OperandVector &Operands) { |
1360 | 692k | if (implicitExpressionLocation(Operands)) { |
1361 | 1.79k | MCAsmParser &Parser = getParser(); |
1362 | 1.79k | SMLoc Loc = Parser.getLexer().getLoc(); |
1363 | 1.79k | std::unique_ptr<HexagonOperand> Expr = |
1364 | 1.79k | HexagonOperand::CreateImm(nullptr, Loc, Loc); |
1365 | 1.79k | MCExpr const *& Val = Expr->Imm.Val; |
1366 | 1.79k | Operands.push_back(std::move(Expr)); |
1367 | 1.79k | return parseExpression(Val); |
1368 | 1.79k | } |
1369 | 690k | return parseOperand(Operands); |
1370 | 692k | } |
1371 | | |
1372 | | /// Parse an instruction. |
1373 | 30.7k | bool HexagonAsmParser::parseInstruction(OperandVector &Operands) { |
1374 | 30.7k | MCAsmParser &Parser = getParser(); |
1375 | 30.7k | MCAsmLexer &Lexer = getLexer(); |
1376 | 771k | while (true) { |
1377 | 771k | AsmToken const &Token = Parser.getTok(); |
1378 | 771k | switch (Token.getKind()) { |
1379 | 5.74k | case AsmToken::EndOfStatement: { |
1380 | 5.74k | Lexer.Lex(); |
1381 | 5.74k | return false; |
1382 | 0 | } |
1383 | 845 | case AsmToken::LCurly: { |
1384 | 845 | if (!Operands.empty()) |
1385 | 12 | return true; |
1386 | 833 | Operands.push_back( |
1387 | 833 | HexagonOperand::CreateToken(Token.getString(), Token.getLoc())); |
1388 | 833 | Lexer.Lex(); |
1389 | 833 | return false; |
1390 | 845 | } |
1391 | 1.50k | case AsmToken::RCurly: { |
1392 | 1.50k | if (Operands.empty()) { |
1393 | 773 | Operands.push_back( |
1394 | 773 | HexagonOperand::CreateToken(Token.getString(), Token.getLoc())); |
1395 | 773 | Lexer.Lex(); |
1396 | 773 | } |
1397 | 1.50k | return false; |
1398 | 845 | } |
1399 | 27.2k | case AsmToken::Comma: { |
1400 | 27.2k | Lexer.Lex(); |
1401 | 27.2k | continue; |
1402 | 845 | } |
1403 | 419 | case AsmToken::EqualEqual: |
1404 | 502 | case AsmToken::ExclaimEqual: |
1405 | 600 | case AsmToken::GreaterEqual: |
1406 | 788 | case AsmToken::GreaterGreater: |
1407 | 809 | case AsmToken::LessEqual: |
1408 | 928 | case AsmToken::LessLess: { |
1409 | 928 | Operands.push_back(HexagonOperand::CreateToken( |
1410 | 928 | Token.getString().substr(0, 1), Token.getLoc())); |
1411 | 928 | Operands.push_back(HexagonOperand::CreateToken( |
1412 | 928 | Token.getString().substr(1, 1), Token.getLoc())); |
1413 | 928 | Lexer.Lex(); |
1414 | 928 | continue; |
1415 | 809 | } |
1416 | 42.7k | case AsmToken::Hash: { |
1417 | 42.7k | bool MustNotExtend = false; |
1418 | 42.7k | bool ImplicitExpression = implicitExpressionLocation(Operands); |
1419 | 42.7k | std::unique_ptr<HexagonOperand> Expr = HexagonOperand::CreateImm( |
1420 | 42.7k | nullptr, Lexer.getLoc(), Lexer.getLoc()); |
1421 | 42.7k | if (!ImplicitExpression) |
1422 | 42.4k | Operands.push_back( |
1423 | 42.4k | HexagonOperand::CreateToken(Token.getString(), Token.getLoc())); |
1424 | 42.7k | Lexer.Lex(); |
1425 | 42.7k | bool MustExtend = false; |
1426 | 42.7k | bool HiOnly = false; |
1427 | 42.7k | bool LoOnly = false; |
1428 | 42.7k | if (Lexer.is(AsmToken::Hash)) { |
1429 | 4.15k | Lexer.Lex(); |
1430 | 4.15k | MustExtend = true; |
1431 | 38.6k | } else if (ImplicitExpression) |
1432 | 110 | MustNotExtend = true; |
1433 | 42.7k | AsmToken const &Token = Parser.getTok(); |
1434 | 42.7k | if (Token.is(AsmToken::Identifier)) { |
1435 | 5.20k | StringRef String = Token.getString(); |
1436 | 5.20k | AsmToken IDToken = Token; |
1437 | 5.20k | if (String.lower() == "hi") { |
1438 | 14 | HiOnly = true; |
1439 | 5.19k | } else if (String.lower() == "lo") { |
1440 | 71 | LoOnly = true; |
1441 | 71 | } |
1442 | 5.20k | if (HiOnly || LoOnly) { |
1443 | 85 | AsmToken LParen = Lexer.peekTok(); |
1444 | 85 | if (!LParen.is(AsmToken::LParen)) { |
1445 | 85 | HiOnly = false; |
1446 | 85 | LoOnly = false; |
1447 | 85 | } else { |
1448 | 0 | Lexer.Lex(); |
1449 | 0 | } |
1450 | 85 | } |
1451 | 5.20k | } |
1452 | 42.7k | if (parseExpression(Expr->Imm.Val)) |
1453 | 22.6k | return true; |
1454 | 20.1k | int64_t Value; |
1455 | 20.1k | MCContext &Context = Parser.getContext(); |
1456 | 20.1k | assert(Expr->Imm.Val != nullptr); |
1457 | 20.1k | if (Expr->Imm.Val->evaluateAsAbsolute(Value)) { |
1458 | 10.4k | if (HiOnly) |
1459 | 0 | Expr->Imm.Val = MCBinaryExpr::createLShr( |
1460 | 0 | Expr->Imm.Val, MCConstantExpr::create(16, Context), Context); |
1461 | 10.4k | if (HiOnly || LoOnly) |
1462 | 0 | Expr->Imm.Val = MCBinaryExpr::createAnd( |
1463 | 0 | Expr->Imm.Val, MCConstantExpr::create(0xffff, Context), Context); |
1464 | 10.4k | } |
1465 | 20.1k | if (MustNotExtend) |
1466 | 96 | Expr->Imm.Val = HexagonNoExtendOperand::Create(Expr->Imm.Val, Context); |
1467 | 20.1k | Expr->Imm.MustExtend = MustExtend; |
1468 | 20.1k | Operands.push_back(std::move(Expr)); |
1469 | 20.1k | continue; |
1470 | 20.1k | } |
1471 | 692k | default: |
1472 | 692k | break; |
1473 | 771k | } |
1474 | 692k | if (parseExpressionOrOperand(Operands)) |
1475 | 20 | return true; |
1476 | 692k | } |
1477 | 30.7k | } |
1478 | | |
1479 | | bool HexagonAsmParser::ParseInstruction(ParseInstructionInfo &Info, |
1480 | | StringRef Name, |
1481 | | AsmToken ID, |
1482 | 30.7k | OperandVector &Operands, unsigned int &ErrorCode) { |
1483 | 30.7k | getLexer().UnLex(ID); |
1484 | 30.7k | return parseInstruction(Operands); |
1485 | 30.7k | } |
1486 | | |
1487 | | namespace { |
1488 | | MCInst makeCombineInst(int opCode, MCOperand &Rdd, |
1489 | 17 | MCOperand &MO1, MCOperand &MO2) { |
1490 | 17 | MCInst TmpInst; |
1491 | 17 | TmpInst.setOpcode(opCode); |
1492 | 17 | TmpInst.addOperand(Rdd); |
1493 | 17 | TmpInst.addOperand(MO1); |
1494 | 17 | TmpInst.addOperand(MO2); |
1495 | | |
1496 | 17 | return TmpInst; |
1497 | 17 | } |
1498 | | } |
1499 | | |
1500 | | // Define this matcher function after the auto-generated include so we |
1501 | | // have the match class enum definitions. |
1502 | | unsigned HexagonAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, |
1503 | 424k | unsigned Kind) { |
1504 | 424k | HexagonOperand *Op = static_cast<HexagonOperand *>(&AsmOp); |
1505 | | |
1506 | 424k | switch (Kind) { |
1507 | 0 | case MCK_0: { |
1508 | 0 | int64_t Value; |
1509 | 0 | return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Value) && Value == 0 |
1510 | 0 | ? Match_Success |
1511 | 0 | : Match_InvalidOperand; |
1512 | 0 | } |
1513 | 0 | case MCK_1: { |
1514 | 0 | int64_t Value; |
1515 | 0 | return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Value) && Value == 1 |
1516 | 0 | ? Match_Success |
1517 | 0 | : Match_InvalidOperand; |
1518 | 0 | } |
1519 | 0 | case MCK__MINUS_1: { |
1520 | 0 | int64_t Value; |
1521 | 0 | return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Value) && Value == -1 |
1522 | 0 | ? Match_Success |
1523 | 0 | : Match_InvalidOperand; |
1524 | 0 | } |
1525 | 424k | } |
1526 | 424k | if (Op->Kind == HexagonOperand::Token && Kind != InvalidMatchClass) { |
1527 | 56.8k | StringRef myStringRef = StringRef(Op->Tok.Data, Op->Tok.Length); |
1528 | 56.8k | if (matchTokenString(myStringRef.lower()) == (MatchClassKind)Kind) |
1529 | 22 | return Match_Success; |
1530 | 56.8k | if (matchTokenString(myStringRef.upper()) == (MatchClassKind)Kind) |
1531 | 0 | return Match_Success; |
1532 | 56.8k | } |
1533 | | |
1534 | 424k | DEBUG(dbgs() << "Unmatched Operand:"); |
1535 | 424k | DEBUG(Op->dump()); |
1536 | 424k | DEBUG(dbgs() << "\n"); |
1537 | | |
1538 | 424k | return Match_InvalidOperand; |
1539 | 424k | } |
1540 | | |
1541 | 1 | void HexagonAsmParser::OutOfRange(SMLoc IDLoc, long long Val, long long Max) { |
1542 | 1 | std::string errStr; |
1543 | 1 | raw_string_ostream ES(errStr); |
1544 | 1 | ES << "value " << Val << "(" << format_hex(Val, 0) << ") out of range: "; |
1545 | 1 | if (Max >= 0) |
1546 | 0 | ES << "0-" << Max; |
1547 | 1 | else |
1548 | 1 | ES << Max << "-" << (-Max - 1); |
1549 | 1 | Error(IDLoc, ES.str().c_str()); |
1550 | 1 | } |
1551 | | |
1552 | | int HexagonAsmParser::processInstruction(MCInst &Inst, |
1553 | | OperandVector const &Operands, |
1554 | | SMLoc IDLoc, bool &MustExtend) |
1555 | 5.26k | { |
1556 | 5.26k | MCContext &Context = getParser().getContext(); |
1557 | 5.26k | const MCRegisterInfo *RI = getContext().getRegisterInfo(); |
1558 | 5.26k | std::string r = "r"; |
1559 | 5.26k | std::string v = "v"; |
1560 | 5.26k | std::string Colon = ":"; |
1561 | | |
1562 | 5.26k | bool is32bit = false; // used to distinguish between CONST32 and CONST64 |
1563 | 5.26k | switch (Inst.getOpcode()) { |
1564 | 5.24k | default: |
1565 | 5.24k | break; |
1566 | | |
1567 | 5.24k | case Hexagon::M4_mpyrr_addr: |
1568 | 0 | case Hexagon::S4_addi_asl_ri: |
1569 | 0 | case Hexagon::S4_addi_lsr_ri: |
1570 | 0 | case Hexagon::S4_andi_asl_ri: |
1571 | 0 | case Hexagon::S4_andi_lsr_ri: |
1572 | 0 | case Hexagon::S4_ori_asl_ri: |
1573 | 0 | case Hexagon::S4_ori_lsr_ri: |
1574 | 0 | case Hexagon::S4_or_andix: |
1575 | 0 | case Hexagon::S4_subi_asl_ri: |
1576 | 0 | case Hexagon::S4_subi_lsr_ri: { |
1577 | 0 | MCOperand &Ry = Inst.getOperand(0); |
1578 | 0 | MCOperand &src = Inst.getOperand(2); |
1579 | 0 | if (RI->getEncodingValue(Ry.getReg()) != RI->getEncodingValue(src.getReg())) |
1580 | 0 | return Match_InvalidOperand; |
1581 | 0 | break; |
1582 | 0 | } |
1583 | | |
1584 | 0 | case Hexagon::C2_cmpgei: { |
1585 | 0 | MCOperand &MO = Inst.getOperand(2); |
1586 | 0 | MO.setExpr(MCBinaryExpr::createSub( |
1587 | 0 | MO.getExpr(), MCConstantExpr::create(1, Context), Context)); |
1588 | 0 | Inst.setOpcode(Hexagon::C2_cmpgti); |
1589 | 0 | break; |
1590 | 0 | } |
1591 | | |
1592 | 0 | case Hexagon::C2_cmpgeui: { |
1593 | 0 | MCOperand &MO = Inst.getOperand(2); |
1594 | 0 | int64_t Value; |
1595 | 0 | bool Success = MO.getExpr()->evaluateAsAbsolute(Value); |
1596 | 0 | (void)Success; |
1597 | 0 | assert(Success && "Assured by matcher"); |
1598 | 0 | if (Value == 0) { |
1599 | 0 | MCInst TmpInst; |
1600 | 0 | MCOperand &Pd = Inst.getOperand(0); |
1601 | 0 | MCOperand &Rt = Inst.getOperand(1); |
1602 | 0 | TmpInst.setOpcode(Hexagon::C2_cmpeq); |
1603 | 0 | TmpInst.addOperand(Pd); |
1604 | 0 | TmpInst.addOperand(Rt); |
1605 | 0 | TmpInst.addOperand(Rt); |
1606 | 0 | Inst = TmpInst; |
1607 | 0 | } else { |
1608 | 0 | MO.setExpr(MCBinaryExpr::createSub( |
1609 | 0 | MO.getExpr(), MCConstantExpr::create(1, Context), Context)); |
1610 | 0 | Inst.setOpcode(Hexagon::C2_cmpgtui); |
1611 | 0 | } |
1612 | 0 | break; |
1613 | 0 | } |
1614 | 0 | case Hexagon::J2_loop1r: |
1615 | 0 | case Hexagon::J2_loop1i: |
1616 | 0 | case Hexagon::J2_loop0r: |
1617 | 0 | case Hexagon::J2_loop0i: { |
1618 | 0 | MCOperand &MO = Inst.getOperand(0); |
1619 | | // Loop has different opcodes for extended vs not extended, but we should |
1620 | | // not use the other opcode as it is a legacy artifact of TD files. |
1621 | 0 | int64_t Value; |
1622 | 0 | if (MO.getExpr()->evaluateAsAbsolute(Value)) { |
1623 | | // if the operand can fit within a 7:2 field |
1624 | 0 | if (Value < (1 << 8) && Value >= -(1 << 8)) { |
1625 | 0 | SMLoc myLoc = Operands[2]->getStartLoc(); |
1626 | | // # is left in startLoc in the case of ## |
1627 | | // If '##' found then force extension. |
1628 | 0 | if (*myLoc.getPointer() == '#') { |
1629 | 0 | MustExtend = true; |
1630 | 0 | break; |
1631 | 0 | } |
1632 | 0 | } else { |
1633 | | // If immediate and out of 7:2 range. |
1634 | 0 | MustExtend = true; |
1635 | 0 | } |
1636 | 0 | } |
1637 | 0 | break; |
1638 | 0 | } |
1639 | | |
1640 | | // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)" |
1641 | 1 | case Hexagon::A2_tfrp: { |
1642 | 1 | MCOperand &MO = Inst.getOperand(1); |
1643 | 1 | unsigned int RegPairNum = RI->getEncodingValue(MO.getReg()); |
1644 | 1 | std::string R1 = r + llvm_ks::utostr(RegPairNum + 1); |
1645 | 1 | StringRef Reg1(R1); |
1646 | 1 | MO.setReg(MatchRegisterName(Reg1)); |
1647 | | // Add a new operand for the second register in the pair. |
1648 | 1 | std::string R2 = r + llvm_ks::utostr(RegPairNum); |
1649 | 1 | StringRef Reg2(R2); |
1650 | 1 | Inst.addOperand(MCOperand::createReg(MatchRegisterName(Reg2))); |
1651 | 1 | Inst.setOpcode(Hexagon::A2_combinew); |
1652 | 1 | break; |
1653 | 0 | } |
1654 | | |
1655 | 0 | case Hexagon::A2_tfrpt: |
1656 | 0 | case Hexagon::A2_tfrpf: { |
1657 | 0 | MCOperand &MO = Inst.getOperand(2); |
1658 | 0 | unsigned int RegPairNum = RI->getEncodingValue(MO.getReg()); |
1659 | 0 | std::string R1 = r + llvm_ks::utostr(RegPairNum + 1); |
1660 | 0 | StringRef Reg1(R1); |
1661 | 0 | MO.setReg(MatchRegisterName(Reg1)); |
1662 | | // Add a new operand for the second register in the pair. |
1663 | 0 | std::string R2 = r + llvm_ks::utostr(RegPairNum); |
1664 | 0 | StringRef Reg2(R2); |
1665 | 0 | Inst.addOperand(MCOperand::createReg(MatchRegisterName(Reg2))); |
1666 | 0 | Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt) |
1667 | 0 | ? Hexagon::C2_ccombinewt |
1668 | 0 | : Hexagon::C2_ccombinewf); |
1669 | 0 | break; |
1670 | 0 | } |
1671 | 0 | case Hexagon::A2_tfrptnew: |
1672 | 0 | case Hexagon::A2_tfrpfnew: { |
1673 | 0 | MCOperand &MO = Inst.getOperand(2); |
1674 | 0 | unsigned int RegPairNum = RI->getEncodingValue(MO.getReg()); |
1675 | 0 | std::string R1 = r + llvm_ks::utostr(RegPairNum + 1); |
1676 | 0 | StringRef Reg1(R1); |
1677 | 0 | MO.setReg(MatchRegisterName(Reg1)); |
1678 | | // Add a new operand for the second register in the pair. |
1679 | 0 | std::string R2 = r + llvm_ks::utostr(RegPairNum); |
1680 | 0 | StringRef Reg2(R2); |
1681 | 0 | Inst.addOperand(MCOperand::createReg(MatchRegisterName(Reg2))); |
1682 | 0 | Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew) |
1683 | 0 | ? Hexagon::C2_ccombinewnewt |
1684 | 0 | : Hexagon::C2_ccombinewnewf); |
1685 | 0 | break; |
1686 | 0 | } |
1687 | | |
1688 | | // Translate a "$Rx = CONST32(#imm)" to "$Rx = memw(gp+#LABEL) " |
1689 | 0 | case Hexagon::CONST32: |
1690 | 0 | case Hexagon::CONST32_Float_Real: |
1691 | 0 | case Hexagon::CONST32_Int_Real: |
1692 | 0 | case Hexagon::FCONST32_nsdata: |
1693 | 0 | is32bit = true; |
1694 | | // Translate a "$Rx:y = CONST64(#imm)" to "$Rx:y = memd(gp+#LABEL) " |
1695 | 0 | case Hexagon::CONST64_Float_Real: |
1696 | 0 | case Hexagon::CONST64_Int_Real: |
1697 | | |
1698 | | // FIXME: need better way to detect AsmStreamer (upstream removed getKind()) |
1699 | 0 | if (!Parser.getStreamer().hasRawTextSupport()) { |
1700 | 0 | MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer()); |
1701 | 0 | MCOperand &MO_1 = Inst.getOperand(1); |
1702 | 0 | MCOperand &MO_0 = Inst.getOperand(0); |
1703 | | |
1704 | | // push section onto section stack |
1705 | 0 | MES->PushSection(); |
1706 | |
|
1707 | 0 | std::string myCharStr; |
1708 | 0 | MCSectionELF *mySection; |
1709 | | |
1710 | | // check if this as an immediate or a symbol |
1711 | 0 | int64_t Value; |
1712 | 0 | bool Absolute = MO_1.getExpr()->evaluateAsAbsolute(Value); |
1713 | 0 | if (Absolute) { |
1714 | | // Create a new section - one for each constant |
1715 | | // Some or all of the zeros are replaced with the given immediate. |
1716 | 0 | if (is32bit) { |
1717 | 0 | std::string myImmStr = utohexstr(static_cast<uint32_t>(Value)); |
1718 | 0 | myCharStr = StringRef(".gnu.linkonce.l4.CONST_00000000") |
1719 | 0 | .drop_back(myImmStr.size()) |
1720 | 0 | .str() + |
1721 | 0 | myImmStr; |
1722 | 0 | } else { |
1723 | 0 | std::string myImmStr = utohexstr(Value); |
1724 | 0 | myCharStr = StringRef(".gnu.linkonce.l8.CONST_0000000000000000") |
1725 | 0 | .drop_back(myImmStr.size()) |
1726 | 0 | .str() + |
1727 | 0 | myImmStr; |
1728 | 0 | } |
1729 | |
|
1730 | 0 | mySection = getContext().getELFSection(myCharStr, ELF::SHT_PROGBITS, |
1731 | 0 | ELF::SHF_ALLOC | ELF::SHF_WRITE); |
1732 | 0 | } else if (MO_1.isExpr()) { |
1733 | | // .lita - for expressions |
1734 | 0 | myCharStr = ".lita"; |
1735 | 0 | mySection = getContext().getELFSection(myCharStr, ELF::SHT_PROGBITS, |
1736 | 0 | ELF::SHF_ALLOC | ELF::SHF_WRITE); |
1737 | 0 | } else |
1738 | 0 | llvm_unreachable("unexpected type of machine operand!"); |
1739 | | |
1740 | 0 | MES->SwitchSection(mySection); |
1741 | 0 | unsigned byteSize = is32bit ? 4 : 8; |
1742 | 0 | getStreamer().EmitCodeAlignment(byteSize, byteSize); |
1743 | |
|
1744 | 0 | MCSymbol *Sym; |
1745 | | |
1746 | | // for symbols, get rid of prepended ".gnu.linkonce.lx." |
1747 | | |
1748 | | // emit symbol if needed |
1749 | 0 | if (Absolute) { |
1750 | 0 | Sym = getContext().getOrCreateSymbol(StringRef(myCharStr.c_str() + 16)); |
1751 | 0 | if (Sym->isUndefined()) { |
1752 | 0 | bool Error; |
1753 | 0 | getStreamer().EmitLabel(Sym); |
1754 | 0 | getStreamer().EmitSymbolAttribute(Sym, MCSA_Global); |
1755 | 0 | getStreamer().EmitIntValue(Value, byteSize, Error); |
1756 | 0 | if (Error) |
1757 | 0 | return Match_InvalidOperand; |
1758 | 0 | } |
1759 | 0 | } else if (MO_1.isExpr()) { |
1760 | 0 | const char *StringStart = 0; |
1761 | 0 | const char *StringEnd = 0; |
1762 | 0 | if (*Operands[4]->getStartLoc().getPointer() == '#') { |
1763 | 0 | StringStart = Operands[5]->getStartLoc().getPointer(); |
1764 | 0 | StringEnd = Operands[6]->getStartLoc().getPointer(); |
1765 | 0 | } else { // no pound |
1766 | 0 | StringStart = Operands[4]->getStartLoc().getPointer(); |
1767 | 0 | StringEnd = Operands[5]->getStartLoc().getPointer(); |
1768 | 0 | } |
1769 | |
|
1770 | 0 | unsigned size = StringEnd - StringStart; |
1771 | 0 | std::string DotConst = ".CONST_"; |
1772 | 0 | Sym = getContext().getOrCreateSymbol(DotConst + |
1773 | 0 | StringRef(StringStart, size)); |
1774 | |
|
1775 | 0 | if (Sym->isUndefined()) { |
1776 | | // case where symbol is not yet defined: emit symbol |
1777 | 0 | getStreamer().EmitLabel(Sym); |
1778 | 0 | getStreamer().EmitSymbolAttribute(Sym, MCSA_Local); |
1779 | 0 | getStreamer().EmitValue(MO_1.getExpr(), 4); |
1780 | 0 | } |
1781 | 0 | } else |
1782 | 0 | llvm_unreachable("unexpected type of machine operand!"); |
1783 | | |
1784 | 0 | MES->PopSection(); |
1785 | |
|
1786 | 0 | if (Sym) { |
1787 | 0 | MCInst TmpInst; |
1788 | 0 | if (is32bit) // 32 bit |
1789 | 0 | TmpInst.setOpcode(Hexagon::L2_loadrigp); |
1790 | 0 | else // 64 bit |
1791 | 0 | TmpInst.setOpcode(Hexagon::L2_loadrdgp); |
1792 | |
|
1793 | 0 | TmpInst.addOperand(MO_0); |
1794 | 0 | TmpInst.addOperand( |
1795 | 0 | MCOperand::createExpr(MCSymbolRefExpr::create(Sym, getContext()))); |
1796 | 0 | Inst = TmpInst; |
1797 | 0 | } |
1798 | 0 | } |
1799 | 0 | break; |
1800 | | |
1801 | | // Translate a "$Rdd = #-imm" to "$Rdd = combine(#[-1,0], #-imm)" |
1802 | 1 | case Hexagon::A2_tfrpi: { |
1803 | 1 | MCOperand &Rdd = Inst.getOperand(0); |
1804 | 1 | MCOperand &MO = Inst.getOperand(1); |
1805 | 1 | int64_t Value; |
1806 | 1 | int sVal = (MO.getExpr()->evaluateAsAbsolute(Value) && Value < 0) ? -1 : 0; |
1807 | 1 | MCOperand imm(MCOperand::createExpr(MCConstantExpr::create(sVal, Context))); |
1808 | 1 | Inst = makeCombineInst(Hexagon::A2_combineii, Rdd, imm, MO); |
1809 | 1 | break; |
1810 | 0 | } |
1811 | | |
1812 | | // Translate a "$Rdd = [#]#imm" to "$Rdd = combine(#, [#]#imm)" |
1813 | 16 | case Hexagon::TFRI64_V4: { |
1814 | 16 | MCOperand &Rdd = Inst.getOperand(0); |
1815 | 16 | MCOperand &MO = Inst.getOperand(1); |
1816 | 16 | int64_t Value; |
1817 | 16 | if (MO.getExpr()->evaluateAsAbsolute(Value)) { |
1818 | 16 | unsigned long long u64 = Value; |
1819 | 16 | signed int s8 = (u64 >> 32) & 0xFFFFFFFF; |
1820 | 16 | if (s8 < -128 || s8 > 127) |
1821 | 1 | OutOfRange(IDLoc, s8, -128); |
1822 | 16 | MCOperand imm(MCOperand::createExpr( |
1823 | 16 | MCConstantExpr::create(s8, Context))); // upper 32 |
1824 | 16 | MCOperand imm2(MCOperand::createExpr( |
1825 | 16 | MCConstantExpr::create(u64 & 0xFFFFFFFF, Context))); // lower 32 |
1826 | 16 | Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, imm, imm2); |
1827 | 16 | } else { |
1828 | 0 | MCOperand imm(MCOperand::createExpr( |
1829 | 0 | MCConstantExpr::create(0, Context))); // upper 32 |
1830 | 0 | Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, imm, MO); |
1831 | 0 | } |
1832 | 16 | break; |
1833 | 0 | } |
1834 | | |
1835 | | // Handle $Rdd = combine(##imm, #imm)" |
1836 | 0 | case Hexagon::TFRI64_V2_ext: { |
1837 | 0 | MCOperand &Rdd = Inst.getOperand(0); |
1838 | 0 | MCOperand &MO1 = Inst.getOperand(1); |
1839 | 0 | MCOperand &MO2 = Inst.getOperand(2); |
1840 | 0 | int64_t Value; |
1841 | 0 | if (MO2.getExpr()->evaluateAsAbsolute(Value)) { |
1842 | 0 | int s8 = Value; |
1843 | 0 | if (s8 < -128 || s8 > 127) |
1844 | 0 | OutOfRange(IDLoc, s8, -128); |
1845 | 0 | } |
1846 | 0 | Inst = makeCombineInst(Hexagon::A2_combineii, Rdd, MO1, MO2); |
1847 | 0 | break; |
1848 | 0 | } |
1849 | | |
1850 | | // Handle $Rdd = combine(#imm, ##imm)" |
1851 | 0 | case Hexagon::A4_combineii: { |
1852 | 0 | MCOperand &Rdd = Inst.getOperand(0); |
1853 | 0 | MCOperand &MO1 = Inst.getOperand(1); |
1854 | 0 | int64_t Value; |
1855 | 0 | if (MO1.getExpr()->evaluateAsAbsolute(Value)) { |
1856 | 0 | int s8 = Value; |
1857 | 0 | if (s8 < -128 || s8 > 127) |
1858 | 0 | OutOfRange(IDLoc, s8, -128); |
1859 | 0 | } |
1860 | 0 | MCOperand &MO2 = Inst.getOperand(2); |
1861 | 0 | Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, MO1, MO2); |
1862 | 0 | break; |
1863 | 0 | } |
1864 | | |
1865 | 0 | case Hexagon::S2_tableidxb_goodsyntax: { |
1866 | 0 | Inst.setOpcode(Hexagon::S2_tableidxb); |
1867 | 0 | break; |
1868 | 0 | } |
1869 | | |
1870 | 0 | case Hexagon::S2_tableidxh_goodsyntax: { |
1871 | 0 | MCInst TmpInst; |
1872 | 0 | MCOperand &Rx = Inst.getOperand(0); |
1873 | 0 | MCOperand &_dst_ = Inst.getOperand(1); |
1874 | 0 | MCOperand &Rs = Inst.getOperand(2); |
1875 | 0 | MCOperand &Imm4 = Inst.getOperand(3); |
1876 | 0 | MCOperand &Imm6 = Inst.getOperand(4); |
1877 | 0 | Imm6.setExpr(MCBinaryExpr::createSub( |
1878 | 0 | Imm6.getExpr(), MCConstantExpr::create(1, Context), Context)); |
1879 | 0 | TmpInst.setOpcode(Hexagon::S2_tableidxh); |
1880 | 0 | TmpInst.addOperand(Rx); |
1881 | 0 | TmpInst.addOperand(_dst_); |
1882 | 0 | TmpInst.addOperand(Rs); |
1883 | 0 | TmpInst.addOperand(Imm4); |
1884 | 0 | TmpInst.addOperand(Imm6); |
1885 | 0 | Inst = TmpInst; |
1886 | 0 | break; |
1887 | 0 | } |
1888 | | |
1889 | 0 | case Hexagon::S2_tableidxw_goodsyntax: { |
1890 | 0 | MCInst TmpInst; |
1891 | 0 | MCOperand &Rx = Inst.getOperand(0); |
1892 | 0 | MCOperand &_dst_ = Inst.getOperand(1); |
1893 | 0 | MCOperand &Rs = Inst.getOperand(2); |
1894 | 0 | MCOperand &Imm4 = Inst.getOperand(3); |
1895 | 0 | MCOperand &Imm6 = Inst.getOperand(4); |
1896 | 0 | Imm6.setExpr(MCBinaryExpr::createSub( |
1897 | 0 | Imm6.getExpr(), MCConstantExpr::create(2, Context), Context)); |
1898 | 0 | TmpInst.setOpcode(Hexagon::S2_tableidxw); |
1899 | 0 | TmpInst.addOperand(Rx); |
1900 | 0 | TmpInst.addOperand(_dst_); |
1901 | 0 | TmpInst.addOperand(Rs); |
1902 | 0 | TmpInst.addOperand(Imm4); |
1903 | 0 | TmpInst.addOperand(Imm6); |
1904 | 0 | Inst = TmpInst; |
1905 | 0 | break; |
1906 | 0 | } |
1907 | | |
1908 | 0 | case Hexagon::S2_tableidxd_goodsyntax: { |
1909 | 0 | MCInst TmpInst; |
1910 | 0 | MCOperand &Rx = Inst.getOperand(0); |
1911 | 0 | MCOperand &_dst_ = Inst.getOperand(1); |
1912 | 0 | MCOperand &Rs = Inst.getOperand(2); |
1913 | 0 | MCOperand &Imm4 = Inst.getOperand(3); |
1914 | 0 | MCOperand &Imm6 = Inst.getOperand(4); |
1915 | 0 | Imm6.setExpr(MCBinaryExpr::createSub( |
1916 | 0 | Imm6.getExpr(), MCConstantExpr::create(3, Context), Context)); |
1917 | 0 | TmpInst.setOpcode(Hexagon::S2_tableidxd); |
1918 | 0 | TmpInst.addOperand(Rx); |
1919 | 0 | TmpInst.addOperand(_dst_); |
1920 | 0 | TmpInst.addOperand(Rs); |
1921 | 0 | TmpInst.addOperand(Imm4); |
1922 | 0 | TmpInst.addOperand(Imm6); |
1923 | 0 | Inst = TmpInst; |
1924 | 0 | break; |
1925 | 0 | } |
1926 | | |
1927 | 0 | case Hexagon::M2_mpyui: { |
1928 | 0 | Inst.setOpcode(Hexagon::M2_mpyi); |
1929 | 0 | break; |
1930 | 0 | } |
1931 | 0 | case Hexagon::M2_mpysmi: { |
1932 | 0 | MCInst TmpInst; |
1933 | 0 | MCOperand &Rd = Inst.getOperand(0); |
1934 | 0 | MCOperand &Rs = Inst.getOperand(1); |
1935 | 0 | MCOperand &Imm = Inst.getOperand(2); |
1936 | 0 | int64_t Value; |
1937 | 0 | bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value); |
1938 | 0 | assert(Absolute); |
1939 | 0 | (void)Absolute; |
1940 | 0 | if (!MustExtend) { |
1941 | 0 | if (Value < 0 && Value > -256) { |
1942 | 0 | Imm.setExpr(MCConstantExpr::create(Value * -1, Context)); |
1943 | 0 | TmpInst.setOpcode(Hexagon::M2_mpysin); |
1944 | 0 | } else if (Value < 256 && Value >= 0) |
1945 | 0 | TmpInst.setOpcode(Hexagon::M2_mpysip); |
1946 | 0 | else |
1947 | 0 | return Match_InvalidOperand; |
1948 | 0 | } else { |
1949 | 0 | if (Value >= 0) |
1950 | 0 | TmpInst.setOpcode(Hexagon::M2_mpysip); |
1951 | 0 | else |
1952 | 0 | return Match_InvalidOperand; |
1953 | 0 | } |
1954 | 0 | TmpInst.addOperand(Rd); |
1955 | 0 | TmpInst.addOperand(Rs); |
1956 | 0 | TmpInst.addOperand(Imm); |
1957 | 0 | Inst = TmpInst; |
1958 | 0 | break; |
1959 | 0 | } |
1960 | | |
1961 | 0 | case Hexagon::S2_asr_i_r_rnd_goodsyntax: { |
1962 | 0 | MCOperand &Imm = Inst.getOperand(2); |
1963 | 0 | MCInst TmpInst; |
1964 | 0 | int64_t Value; |
1965 | 0 | bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value); |
1966 | 0 | assert(Absolute); |
1967 | 0 | (void)Absolute; |
1968 | 0 | if (Value == 0) { // convert to $Rd = $Rs |
1969 | 0 | TmpInst.setOpcode(Hexagon::A2_tfr); |
1970 | 0 | MCOperand &Rd = Inst.getOperand(0); |
1971 | 0 | MCOperand &Rs = Inst.getOperand(1); |
1972 | 0 | TmpInst.addOperand(Rd); |
1973 | 0 | TmpInst.addOperand(Rs); |
1974 | 0 | } else { |
1975 | 0 | Imm.setExpr(MCBinaryExpr::createSub( |
1976 | 0 | Imm.getExpr(), MCConstantExpr::create(1, Context), Context)); |
1977 | 0 | TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd); |
1978 | 0 | MCOperand &Rd = Inst.getOperand(0); |
1979 | 0 | MCOperand &Rs = Inst.getOperand(1); |
1980 | 0 | TmpInst.addOperand(Rd); |
1981 | 0 | TmpInst.addOperand(Rs); |
1982 | 0 | TmpInst.addOperand(Imm); |
1983 | 0 | } |
1984 | 0 | Inst = TmpInst; |
1985 | 0 | break; |
1986 | 0 | } |
1987 | | |
1988 | 0 | case Hexagon::S2_asr_i_p_rnd_goodsyntax: { |
1989 | 0 | MCOperand &Rdd = Inst.getOperand(0); |
1990 | 0 | MCOperand &Rss = Inst.getOperand(1); |
1991 | 0 | MCOperand &Imm = Inst.getOperand(2); |
1992 | 0 | int64_t Value; |
1993 | 0 | bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value); |
1994 | 0 | assert(Absolute); |
1995 | 0 | (void)Absolute; |
1996 | 0 | if (Value == 0) { // convert to $Rdd = combine ($Rs[0], $Rs[1]) |
1997 | 0 | MCInst TmpInst; |
1998 | 0 | unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg()); |
1999 | 0 | std::string R1 = r + llvm_ks::utostr(RegPairNum + 1); |
2000 | 0 | StringRef Reg1(R1); |
2001 | 0 | Rss.setReg(MatchRegisterName(Reg1)); |
2002 | | // Add a new operand for the second register in the pair. |
2003 | 0 | std::string R2 = r + llvm_ks::utostr(RegPairNum); |
2004 | 0 | StringRef Reg2(R2); |
2005 | 0 | TmpInst.setOpcode(Hexagon::A2_combinew); |
2006 | 0 | TmpInst.addOperand(Rdd); |
2007 | 0 | TmpInst.addOperand(Rss); |
2008 | 0 | TmpInst.addOperand(MCOperand::createReg(MatchRegisterName(Reg2))); |
2009 | 0 | Inst = TmpInst; |
2010 | 0 | } else { |
2011 | 0 | Imm.setExpr(MCBinaryExpr::createSub( |
2012 | 0 | Imm.getExpr(), MCConstantExpr::create(1, Context), Context)); |
2013 | 0 | Inst.setOpcode(Hexagon::S2_asr_i_p_rnd); |
2014 | 0 | } |
2015 | 0 | break; |
2016 | 0 | } |
2017 | | |
2018 | 0 | case Hexagon::A4_boundscheck: { |
2019 | 0 | MCOperand &Rs = Inst.getOperand(1); |
2020 | 0 | unsigned int RegNum = RI->getEncodingValue(Rs.getReg()); |
2021 | 0 | if (RegNum & 1) { // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2 |
2022 | 0 | Inst.setOpcode(Hexagon::A4_boundscheck_hi); |
2023 | 0 | std::string Name = |
2024 | 0 | r + llvm_ks::utostr(RegNum) + Colon + llvm_ks::utostr(RegNum - 1); |
2025 | 0 | StringRef RegPair = Name; |
2026 | 0 | Rs.setReg(MatchRegisterName(RegPair)); |
2027 | 0 | } else { // raw:lo |
2028 | 0 | Inst.setOpcode(Hexagon::A4_boundscheck_lo); |
2029 | 0 | std::string Name = |
2030 | 0 | r + llvm_ks::utostr(RegNum + 1) + Colon + llvm_ks::utostr(RegNum); |
2031 | 0 | StringRef RegPair = Name; |
2032 | 0 | Rs.setReg(MatchRegisterName(RegPair)); |
2033 | 0 | } |
2034 | 0 | break; |
2035 | 0 | } |
2036 | | |
2037 | 0 | case Hexagon::A2_addsp: { |
2038 | 0 | MCOperand &Rs = Inst.getOperand(1); |
2039 | 0 | unsigned int RegNum = RI->getEncodingValue(Rs.getReg()); |
2040 | 0 | if (RegNum & 1) { // Odd mapped to raw:hi |
2041 | 0 | Inst.setOpcode(Hexagon::A2_addsph); |
2042 | 0 | std::string Name = |
2043 | 0 | r + llvm_ks::utostr(RegNum) + Colon + llvm_ks::utostr(RegNum - 1); |
2044 | 0 | StringRef RegPair = Name; |
2045 | 0 | Rs.setReg(MatchRegisterName(RegPair)); |
2046 | 0 | } else { // Even mapped raw:lo |
2047 | 0 | Inst.setOpcode(Hexagon::A2_addspl); |
2048 | 0 | std::string Name = |
2049 | 0 | r + llvm_ks::utostr(RegNum + 1) + Colon + llvm_ks::utostr(RegNum); |
2050 | 0 | StringRef RegPair = Name; |
2051 | 0 | Rs.setReg(MatchRegisterName(RegPair)); |
2052 | 0 | } |
2053 | 0 | break; |
2054 | 0 | } |
2055 | | |
2056 | 0 | case Hexagon::M2_vrcmpys_s1: { |
2057 | 0 | MCOperand &Rt = Inst.getOperand(2); |
2058 | 0 | unsigned int RegNum = RI->getEncodingValue(Rt.getReg()); |
2059 | 0 | if (RegNum & 1) { // Odd mapped to sat:raw:hi |
2060 | 0 | Inst.setOpcode(Hexagon::M2_vrcmpys_s1_h); |
2061 | 0 | std::string Name = |
2062 | 0 | r + llvm_ks::utostr(RegNum) + Colon + llvm_ks::utostr(RegNum - 1); |
2063 | 0 | StringRef RegPair = Name; |
2064 | 0 | Rt.setReg(MatchRegisterName(RegPair)); |
2065 | 0 | } else { // Even mapped sat:raw:lo |
2066 | 0 | Inst.setOpcode(Hexagon::M2_vrcmpys_s1_l); |
2067 | 0 | std::string Name = |
2068 | 0 | r + llvm_ks::utostr(RegNum + 1) + Colon + llvm_ks::utostr(RegNum); |
2069 | 0 | StringRef RegPair = Name; |
2070 | 0 | Rt.setReg(MatchRegisterName(RegPair)); |
2071 | 0 | } |
2072 | 0 | break; |
2073 | 0 | } |
2074 | | |
2075 | 0 | case Hexagon::M2_vrcmpys_acc_s1: { |
2076 | 0 | MCInst TmpInst; |
2077 | 0 | MCOperand &Rxx = Inst.getOperand(0); |
2078 | 0 | MCOperand &Rss = Inst.getOperand(2); |
2079 | 0 | MCOperand &Rt = Inst.getOperand(3); |
2080 | 0 | unsigned int RegNum = RI->getEncodingValue(Rt.getReg()); |
2081 | 0 | if (RegNum & 1) { // Odd mapped to sat:raw:hi |
2082 | 0 | TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h); |
2083 | 0 | std::string Name = |
2084 | 0 | r + llvm_ks::utostr(RegNum) + Colon + llvm_ks::utostr(RegNum - 1); |
2085 | 0 | StringRef RegPair = Name; |
2086 | 0 | Rt.setReg(MatchRegisterName(RegPair)); |
2087 | 0 | } else { // Even mapped sat:raw:lo |
2088 | 0 | TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l); |
2089 | 0 | std::string Name = |
2090 | 0 | r + llvm_ks::utostr(RegNum + 1) + Colon + llvm_ks::utostr(RegNum); |
2091 | 0 | StringRef RegPair = Name; |
2092 | 0 | Rt.setReg(MatchRegisterName(RegPair)); |
2093 | 0 | } |
2094 | | // Registers are in different positions |
2095 | 0 | TmpInst.addOperand(Rxx); |
2096 | 0 | TmpInst.addOperand(Rxx); |
2097 | 0 | TmpInst.addOperand(Rss); |
2098 | 0 | TmpInst.addOperand(Rt); |
2099 | 0 | Inst = TmpInst; |
2100 | 0 | break; |
2101 | 0 | } |
2102 | | |
2103 | 0 | case Hexagon::M2_vrcmpys_s1rp: { |
2104 | 0 | MCOperand &Rt = Inst.getOperand(2); |
2105 | 0 | unsigned int RegNum = RI->getEncodingValue(Rt.getReg()); |
2106 | 0 | if (RegNum & 1) { // Odd mapped to rnd:sat:raw:hi |
2107 | 0 | Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h); |
2108 | 0 | std::string Name = |
2109 | 0 | r + llvm_ks::utostr(RegNum) + Colon + llvm_ks::utostr(RegNum - 1); |
2110 | 0 | StringRef RegPair = Name; |
2111 | 0 | Rt.setReg(MatchRegisterName(RegPair)); |
2112 | 0 | } else { // Even mapped rnd:sat:raw:lo |
2113 | 0 | Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l); |
2114 | 0 | std::string Name = |
2115 | 0 | r + llvm_ks::utostr(RegNum + 1) + Colon + llvm_ks::utostr(RegNum); |
2116 | 0 | StringRef RegPair = Name; |
2117 | 0 | Rt.setReg(MatchRegisterName(RegPair)); |
2118 | 0 | } |
2119 | 0 | break; |
2120 | 0 | } |
2121 | | |
2122 | 0 | case Hexagon::S5_asrhub_rnd_sat_goodsyntax: { |
2123 | 0 | MCOperand &Imm = Inst.getOperand(2); |
2124 | 0 | int64_t Value; |
2125 | 0 | bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value); |
2126 | 0 | assert(Absolute); |
2127 | 0 | (void)Absolute; |
2128 | 0 | if (Value == 0) |
2129 | 0 | Inst.setOpcode(Hexagon::S2_vsathub); |
2130 | 0 | else { |
2131 | 0 | Imm.setExpr(MCBinaryExpr::createSub( |
2132 | 0 | Imm.getExpr(), MCConstantExpr::create(1, Context), Context)); |
2133 | 0 | Inst.setOpcode(Hexagon::S5_asrhub_rnd_sat); |
2134 | 0 | } |
2135 | 0 | break; |
2136 | 0 | } |
2137 | | |
2138 | 0 | case Hexagon::S5_vasrhrnd_goodsyntax: { |
2139 | 0 | MCOperand &Rdd = Inst.getOperand(0); |
2140 | 0 | MCOperand &Rss = Inst.getOperand(1); |
2141 | 0 | MCOperand &Imm = Inst.getOperand(2); |
2142 | 0 | int64_t Value; |
2143 | 0 | bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value); |
2144 | 0 | assert(Absolute); |
2145 | 0 | (void)Absolute; |
2146 | 0 | if (Value == 0) { |
2147 | 0 | MCInst TmpInst; |
2148 | 0 | unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg()); |
2149 | 0 | std::string R1 = r + llvm_ks::utostr(RegPairNum + 1); |
2150 | 0 | StringRef Reg1(R1); |
2151 | 0 | Rss.setReg(MatchRegisterName(Reg1)); |
2152 | | // Add a new operand for the second register in the pair. |
2153 | 0 | std::string R2 = r + llvm_ks::utostr(RegPairNum); |
2154 | 0 | StringRef Reg2(R2); |
2155 | 0 | TmpInst.setOpcode(Hexagon::A2_combinew); |
2156 | 0 | TmpInst.addOperand(Rdd); |
2157 | 0 | TmpInst.addOperand(Rss); |
2158 | 0 | TmpInst.addOperand(MCOperand::createReg(MatchRegisterName(Reg2))); |
2159 | 0 | Inst = TmpInst; |
2160 | 0 | } else { |
2161 | 0 | Imm.setExpr(MCBinaryExpr::createSub( |
2162 | 0 | Imm.getExpr(), MCConstantExpr::create(1, Context), Context)); |
2163 | 0 | Inst.setOpcode(Hexagon::S5_vasrhrnd); |
2164 | 0 | } |
2165 | 0 | break; |
2166 | 0 | } |
2167 | | |
2168 | 0 | case Hexagon::A2_not: { |
2169 | 0 | MCInst TmpInst; |
2170 | 0 | MCOperand &Rd = Inst.getOperand(0); |
2171 | 0 | MCOperand &Rs = Inst.getOperand(1); |
2172 | 0 | TmpInst.setOpcode(Hexagon::A2_subri); |
2173 | 0 | TmpInst.addOperand(Rd); |
2174 | 0 | TmpInst.addOperand( |
2175 | 0 | MCOperand::createExpr(MCConstantExpr::create(-1, Context))); |
2176 | 0 | TmpInst.addOperand(Rs); |
2177 | 0 | Inst = TmpInst; |
2178 | 0 | break; |
2179 | 0 | } |
2180 | 5.26k | } // switch |
2181 | | |
2182 | 5.26k | return Match_Success; |
2183 | 5.26k | } |