1303231Sdim//===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim 9314564Sdim#include "LanaiAluCode.h" 10314564Sdim#include "LanaiCondCode.h" 11353358Sdim#include "LanaiInstrInfo.h" 12303231Sdim#include "MCTargetDesc/LanaiMCExpr.h" 13353358Sdim#include "TargetInfo/LanaiTargetInfo.h" 14303231Sdim#include "llvm/ADT/STLExtras.h" 15314564Sdim#include "llvm/ADT/StringRef.h" 16314564Sdim#include "llvm/ADT/StringSwitch.h" 17303231Sdim#include "llvm/MC/MCContext.h" 18303231Sdim#include "llvm/MC/MCExpr.h" 19303231Sdim#include "llvm/MC/MCInst.h" 20303231Sdim#include "llvm/MC/MCParser/MCAsmLexer.h" 21314564Sdim#include "llvm/MC/MCParser/MCAsmParser.h" 22303231Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 23303231Sdim#include "llvm/MC/MCParser/MCTargetAsmParser.h" 24303231Sdim#include "llvm/MC/MCStreamer.h" 25303231Sdim#include "llvm/MC/MCSubtargetInfo.h" 26303231Sdim#include "llvm/MC/MCSymbol.h" 27314564Sdim#include "llvm/Support/Casting.h" 28314564Sdim#include "llvm/Support/ErrorHandling.h" 29303231Sdim#include "llvm/Support/MathExtras.h" 30314564Sdim#include "llvm/Support/SMLoc.h" 31321369Sdim#include "llvm/Support/TargetRegistry.h" 32314564Sdim#include "llvm/Support/raw_ostream.h" 33314564Sdim#include <algorithm> 34314564Sdim#include <cassert> 35314564Sdim#include <cstddef> 36314564Sdim#include <cstdint> 37314564Sdim#include <memory> 38303231Sdim 39327952Sdimusing namespace llvm; 40314564Sdim 41314564Sdim// Auto-generated by TableGen 42314564Sdimstatic unsigned MatchRegisterName(StringRef Name); 43314564Sdim 44303231Sdimnamespace { 45314564Sdim 46303231Sdimstruct LanaiOperand; 47303231Sdim 48303231Sdimclass LanaiAsmParser : public MCTargetAsmParser { 49303231Sdim // Parse operands 50303231Sdim std::unique_ptr<LanaiOperand> parseRegister(); 51303231Sdim 52303231Sdim std::unique_ptr<LanaiOperand> parseImmediate(); 53303231Sdim 54303231Sdim std::unique_ptr<LanaiOperand> parseIdentifier(); 55303231Sdim 56303231Sdim unsigned parseAluOperator(bool PreOp, bool PostOp); 57303231Sdim 58303231Sdim // Split the mnemonic stripping conditional code and quantifiers 59303231Sdim StringRef splitMnemonic(StringRef Name, SMLoc NameLoc, 60303231Sdim OperandVector *Operands); 61303231Sdim 62303231Sdim bool parsePrePost(StringRef Type, int *OffsetValue); 63303231Sdim 64303231Sdim bool ParseDirective(AsmToken DirectiveID) override; 65303231Sdim 66303231Sdim bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 67303231Sdim SMLoc NameLoc, OperandVector &Operands) override; 68303231Sdim 69303231Sdim bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override; 70303231Sdim 71303231Sdim bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode, 72303231Sdim OperandVector &Operands, MCStreamer &Out, 73303231Sdim uint64_t &ErrorInfo, 74303231Sdim bool MatchingInlineAsm) override; 75303231Sdim 76303231Sdim// Auto-generated instruction matching functions 77303231Sdim#define GET_ASSEMBLER_HEADER 78303231Sdim#include "LanaiGenAsmMatcher.inc" 79303231Sdim 80303231Sdim OperandMatchResultTy parseOperand(OperandVector *Operands, 81303231Sdim StringRef Mnemonic); 82303231Sdim 83303231Sdim OperandMatchResultTy parseMemoryOperand(OperandVector &Operands); 84303231Sdim 85303231Sdimpublic: 86303231Sdim LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 87303231Sdim const MCInstrInfo &MII, const MCTargetOptions &Options) 88327952Sdim : MCTargetAsmParser(Options, STI, MII), Parser(Parser), 89303231Sdim Lexer(Parser.getLexer()), SubtargetInfo(STI) { 90303231Sdim setAvailableFeatures( 91303231Sdim ComputeAvailableFeatures(SubtargetInfo.getFeatureBits())); 92303231Sdim } 93303231Sdim 94303231Sdimprivate: 95303231Sdim MCAsmParser &Parser; 96303231Sdim MCAsmLexer &Lexer; 97303231Sdim 98303231Sdim const MCSubtargetInfo &SubtargetInfo; 99303231Sdim}; 100303231Sdim 101303231Sdim// LanaiOperand - Instances of this class represented a parsed machine 102303231Sdim// instruction 103303231Sdimstruct LanaiOperand : public MCParsedAsmOperand { 104303231Sdim enum KindTy { 105303231Sdim TOKEN, 106303231Sdim REGISTER, 107303231Sdim IMMEDIATE, 108303231Sdim MEMORY_IMM, 109303231Sdim MEMORY_REG_IMM, 110303231Sdim MEMORY_REG_REG, 111303231Sdim } Kind; 112303231Sdim 113303231Sdim SMLoc StartLoc, EndLoc; 114303231Sdim 115303231Sdim struct Token { 116303231Sdim const char *Data; 117303231Sdim unsigned Length; 118303231Sdim }; 119303231Sdim 120303231Sdim struct RegOp { 121303231Sdim unsigned RegNum; 122303231Sdim }; 123303231Sdim 124303231Sdim struct ImmOp { 125303231Sdim const MCExpr *Value; 126303231Sdim }; 127303231Sdim 128303231Sdim struct MemOp { 129303231Sdim unsigned BaseReg; 130303231Sdim unsigned OffsetReg; 131303231Sdim unsigned AluOp; 132303231Sdim const MCExpr *Offset; 133303231Sdim }; 134303231Sdim 135303231Sdim union { 136303231Sdim struct Token Tok; 137303231Sdim struct RegOp Reg; 138303231Sdim struct ImmOp Imm; 139303231Sdim struct MemOp Mem; 140303231Sdim }; 141303231Sdim 142303231Sdim explicit LanaiOperand(KindTy Kind) : MCParsedAsmOperand(), Kind(Kind) {} 143303231Sdim 144303231Sdimpublic: 145303231Sdim // The functions below are used by the autogenerated ASM matcher and hence to 146303231Sdim // be of the form expected. 147303231Sdim 148303231Sdim // getStartLoc - Gets location of the first token of this operand 149303231Sdim SMLoc getStartLoc() const override { return StartLoc; } 150303231Sdim 151303231Sdim // getEndLoc - Gets location of the last token of this operand 152303231Sdim SMLoc getEndLoc() const override { return EndLoc; } 153303231Sdim 154303231Sdim unsigned getReg() const override { 155303231Sdim assert(isReg() && "Invalid type access!"); 156303231Sdim return Reg.RegNum; 157303231Sdim } 158303231Sdim 159303231Sdim const MCExpr *getImm() const { 160303231Sdim assert(isImm() && "Invalid type access!"); 161303231Sdim return Imm.Value; 162303231Sdim } 163303231Sdim 164303231Sdim StringRef getToken() const { 165303231Sdim assert(isToken() && "Invalid type access!"); 166303231Sdim return StringRef(Tok.Data, Tok.Length); 167303231Sdim } 168303231Sdim 169303231Sdim unsigned getMemBaseReg() const { 170303231Sdim assert(isMem() && "Invalid type access!"); 171303231Sdim return Mem.BaseReg; 172303231Sdim } 173303231Sdim 174303231Sdim unsigned getMemOffsetReg() const { 175303231Sdim assert(isMem() && "Invalid type access!"); 176303231Sdim return Mem.OffsetReg; 177303231Sdim } 178303231Sdim 179303231Sdim const MCExpr *getMemOffset() const { 180303231Sdim assert(isMem() && "Invalid type access!"); 181303231Sdim return Mem.Offset; 182303231Sdim } 183303231Sdim 184303231Sdim unsigned getMemOp() const { 185303231Sdim assert(isMem() && "Invalid type access!"); 186303231Sdim return Mem.AluOp; 187303231Sdim } 188303231Sdim 189303231Sdim // Functions for testing operand type 190303231Sdim bool isReg() const override { return Kind == REGISTER; } 191303231Sdim 192303231Sdim bool isImm() const override { return Kind == IMMEDIATE; } 193303231Sdim 194303231Sdim bool isMem() const override { 195303231Sdim return isMemImm() || isMemRegImm() || isMemRegReg(); 196303231Sdim } 197303231Sdim 198303231Sdim bool isMemImm() const { return Kind == MEMORY_IMM; } 199303231Sdim 200303231Sdim bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; } 201303231Sdim 202303231Sdim bool isMemRegReg() const { return Kind == MEMORY_REG_REG; } 203303231Sdim 204303231Sdim bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); } 205303231Sdim 206303231Sdim bool isToken() const override { return Kind == TOKEN; } 207303231Sdim 208303231Sdim bool isBrImm() { 209303231Sdim if (!isImm()) 210303231Sdim return false; 211303231Sdim 212303231Sdim // Constant case 213303231Sdim const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value); 214303231Sdim if (!MCE) 215303231Sdim return true; 216303231Sdim int64_t Value = MCE->getValue(); 217303231Sdim // Check if value fits in 25 bits with 2 least significant bits 0. 218303231Sdim return isShiftedUInt<23, 2>(static_cast<int32_t>(Value)); 219303231Sdim } 220303231Sdim 221303231Sdim bool isBrTarget() { return isBrImm() || isToken(); } 222303231Sdim 223303231Sdim bool isCallTarget() { return isImm() || isToken(); } 224303231Sdim 225303231Sdim bool isHiImm16() { 226303231Sdim if (!isImm()) 227303231Sdim return false; 228303231Sdim 229303231Sdim // Constant case 230303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) { 231303231Sdim int64_t Value = ConstExpr->getValue(); 232303231Sdim return Value != 0 && isShiftedUInt<16, 16>(Value); 233303231Sdim } 234303231Sdim 235303231Sdim // Symbolic reference expression 236303231Sdim if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value)) 237303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI; 238303231Sdim 239303231Sdim // Binary expression 240303231Sdim if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) 241303231Sdim if (const LanaiMCExpr *SymbolRefExpr = 242303231Sdim dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())) 243303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI; 244303231Sdim 245303231Sdim return false; 246303231Sdim } 247303231Sdim 248303231Sdim bool isHiImm16And() { 249303231Sdim if (!isImm()) 250303231Sdim return false; 251303231Sdim 252303231Sdim const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); 253303231Sdim if (ConstExpr) { 254303231Sdim int64_t Value = ConstExpr->getValue(); 255303231Sdim // Check if in the form 0xXYZWffff 256303231Sdim return (Value != 0) && ((Value & ~0xffff0000) == 0xffff); 257303231Sdim } 258303231Sdim return false; 259303231Sdim } 260303231Sdim 261303231Sdim bool isLoImm16() { 262303231Sdim if (!isImm()) 263303231Sdim return false; 264303231Sdim 265303231Sdim // Constant case 266303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) { 267303231Sdim int64_t Value = ConstExpr->getValue(); 268303231Sdim // Check if value fits in 16 bits 269303231Sdim return isUInt<16>(static_cast<int32_t>(Value)); 270303231Sdim } 271303231Sdim 272303231Sdim // Symbolic reference expression 273303231Sdim if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value)) 274303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO; 275303231Sdim 276303231Sdim // Binary expression 277303231Sdim if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) 278303231Sdim if (const LanaiMCExpr *SymbolRefExpr = 279303231Sdim dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())) 280303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO; 281303231Sdim 282303231Sdim return false; 283303231Sdim } 284303231Sdim 285303231Sdim bool isLoImm16Signed() { 286303231Sdim if (!isImm()) 287303231Sdim return false; 288303231Sdim 289303231Sdim // Constant case 290303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) { 291303231Sdim int64_t Value = ConstExpr->getValue(); 292303231Sdim // Check if value fits in 16 bits or value of the form 0xffffxyzw 293303231Sdim return isInt<16>(static_cast<int32_t>(Value)); 294303231Sdim } 295303231Sdim 296303231Sdim // Symbolic reference expression 297303231Sdim if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value)) 298303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO; 299303231Sdim 300303231Sdim // Binary expression 301303231Sdim if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) 302303231Sdim if (const LanaiMCExpr *SymbolRefExpr = 303303231Sdim dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())) 304303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO; 305303231Sdim 306303231Sdim return false; 307303231Sdim } 308303231Sdim 309303231Sdim bool isLoImm16And() { 310303231Sdim if (!isImm()) 311303231Sdim return false; 312303231Sdim 313303231Sdim const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); 314303231Sdim if (ConstExpr) { 315303231Sdim int64_t Value = ConstExpr->getValue(); 316303231Sdim // Check if in the form 0xffffXYZW 317303231Sdim return ((Value & ~0xffff) == 0xffff0000); 318303231Sdim } 319303231Sdim return false; 320303231Sdim } 321303231Sdim 322303231Sdim bool isImmShift() { 323303231Sdim if (!isImm()) 324303231Sdim return false; 325303231Sdim 326303231Sdim const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); 327303231Sdim if (!ConstExpr) 328303231Sdim return false; 329303231Sdim int64_t Value = ConstExpr->getValue(); 330303231Sdim return (Value >= -31) && (Value <= 31); 331303231Sdim } 332303231Sdim 333303231Sdim bool isLoImm21() { 334303231Sdim if (!isImm()) 335303231Sdim return false; 336303231Sdim 337303231Sdim // Constant case 338303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) { 339303231Sdim int64_t Value = ConstExpr->getValue(); 340303231Sdim return isUInt<21>(Value); 341303231Sdim } 342303231Sdim 343303231Sdim // Symbolic reference expression 344303231Sdim if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value)) 345303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None; 346303231Sdim if (const MCSymbolRefExpr *SymbolRefExpr = 347303231Sdim dyn_cast<MCSymbolRefExpr>(Imm.Value)) { 348303231Sdim return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None; 349303231Sdim } 350303231Sdim 351303231Sdim // Binary expression 352303231Sdim if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) { 353303231Sdim if (const LanaiMCExpr *SymbolRefExpr = 354303231Sdim dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())) 355303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None; 356303231Sdim if (const MCSymbolRefExpr *SymbolRefExpr = 357303231Sdim dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS())) 358303231Sdim return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None; 359303231Sdim } 360303231Sdim 361303231Sdim return false; 362303231Sdim } 363303231Sdim 364303231Sdim bool isImm10() { 365303231Sdim if (!isImm()) 366303231Sdim return false; 367303231Sdim 368303231Sdim const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); 369303231Sdim if (!ConstExpr) 370303231Sdim return false; 371303231Sdim int64_t Value = ConstExpr->getValue(); 372303231Sdim return isInt<10>(Value); 373303231Sdim } 374303231Sdim 375303231Sdim bool isCondCode() { 376303231Sdim if (!isImm()) 377303231Sdim return false; 378303231Sdim 379303231Sdim const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value); 380303231Sdim if (!ConstExpr) 381303231Sdim return false; 382303231Sdim uint64_t Value = ConstExpr->getValue(); 383303231Sdim // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the 384303231Sdim // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then 385303231Sdim // value corresponds to a valid condition code. 386303231Sdim return Value < LPCC::UNKNOWN; 387303231Sdim } 388303231Sdim 389303231Sdim void addExpr(MCInst &Inst, const MCExpr *Expr) const { 390303231Sdim // Add as immediates where possible. Null MCExpr = 0 391303231Sdim if (Expr == nullptr) 392303231Sdim Inst.addOperand(MCOperand::createImm(0)); 393303231Sdim else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr)) 394303231Sdim Inst.addOperand( 395303231Sdim MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue()))); 396303231Sdim else 397303231Sdim Inst.addOperand(MCOperand::createExpr(Expr)); 398303231Sdim } 399303231Sdim 400303231Sdim void addRegOperands(MCInst &Inst, unsigned N) const { 401303231Sdim assert(N == 1 && "Invalid number of operands!"); 402303231Sdim Inst.addOperand(MCOperand::createReg(getReg())); 403303231Sdim } 404303231Sdim 405303231Sdim void addImmOperands(MCInst &Inst, unsigned N) const { 406303231Sdim assert(N == 1 && "Invalid number of operands!"); 407303231Sdim addExpr(Inst, getImm()); 408303231Sdim } 409303231Sdim 410303231Sdim void addBrTargetOperands(MCInst &Inst, unsigned N) const { 411303231Sdim assert(N == 1 && "Invalid number of operands!"); 412303231Sdim addExpr(Inst, getImm()); 413303231Sdim } 414303231Sdim 415303231Sdim void addCallTargetOperands(MCInst &Inst, unsigned N) const { 416303231Sdim assert(N == 1 && "Invalid number of operands!"); 417303231Sdim addExpr(Inst, getImm()); 418303231Sdim } 419303231Sdim 420303231Sdim void addCondCodeOperands(MCInst &Inst, unsigned N) const { 421303231Sdim assert(N == 1 && "Invalid number of operands!"); 422303231Sdim addExpr(Inst, getImm()); 423303231Sdim } 424303231Sdim 425303231Sdim void addMemImmOperands(MCInst &Inst, unsigned N) const { 426303231Sdim assert(N == 1 && "Invalid number of operands!"); 427303231Sdim const MCExpr *Expr = getMemOffset(); 428303231Sdim addExpr(Inst, Expr); 429303231Sdim } 430303231Sdim 431303231Sdim void addMemRegImmOperands(MCInst &Inst, unsigned N) const { 432303231Sdim assert(N == 3 && "Invalid number of operands!"); 433303231Sdim Inst.addOperand(MCOperand::createReg(getMemBaseReg())); 434303231Sdim const MCExpr *Expr = getMemOffset(); 435303231Sdim addExpr(Inst, Expr); 436303231Sdim Inst.addOperand(MCOperand::createImm(getMemOp())); 437303231Sdim } 438303231Sdim 439303231Sdim void addMemRegRegOperands(MCInst &Inst, unsigned N) const { 440303231Sdim assert(N == 3 && "Invalid number of operands!"); 441303231Sdim Inst.addOperand(MCOperand::createReg(getMemBaseReg())); 442303231Sdim assert(getMemOffsetReg() != 0 && "Invalid offset"); 443303231Sdim Inst.addOperand(MCOperand::createReg(getMemOffsetReg())); 444303231Sdim Inst.addOperand(MCOperand::createImm(getMemOp())); 445303231Sdim } 446303231Sdim 447303231Sdim void addMemSplsOperands(MCInst &Inst, unsigned N) const { 448303231Sdim if (isMemRegImm()) 449303231Sdim addMemRegImmOperands(Inst, N); 450303231Sdim if (isMemRegReg()) 451303231Sdim addMemRegRegOperands(Inst, N); 452303231Sdim } 453303231Sdim 454303231Sdim void addImmShiftOperands(MCInst &Inst, unsigned N) const { 455303231Sdim assert(N == 1 && "Invalid number of operands!"); 456303231Sdim addExpr(Inst, getImm()); 457303231Sdim } 458303231Sdim 459303231Sdim void addImm10Operands(MCInst &Inst, unsigned N) const { 460303231Sdim assert(N == 1 && "Invalid number of operands!"); 461303231Sdim addExpr(Inst, getImm()); 462303231Sdim } 463303231Sdim 464303231Sdim void addLoImm16Operands(MCInst &Inst, unsigned N) const { 465303231Sdim assert(N == 1 && "Invalid number of operands!"); 466303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) 467303231Sdim Inst.addOperand( 468303231Sdim MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue()))); 469303231Sdim else if (isa<LanaiMCExpr>(getImm())) { 470303231Sdim#ifndef NDEBUG 471303231Sdim const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm()); 472360784Sdim assert(SymbolRefExpr && 473360784Sdim SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO); 474303231Sdim#endif 475303231Sdim Inst.addOperand(MCOperand::createExpr(getImm())); 476303231Sdim } else if (isa<MCBinaryExpr>(getImm())) { 477303231Sdim#ifndef NDEBUG 478303231Sdim const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm()); 479360784Sdim assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) && 480341825Sdim cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() == 481303231Sdim LanaiMCExpr::VK_Lanai_ABS_LO); 482303231Sdim#endif 483303231Sdim Inst.addOperand(MCOperand::createExpr(getImm())); 484303231Sdim } else 485303231Sdim assert(false && "Operand type not supported."); 486303231Sdim } 487303231Sdim 488303231Sdim void addLoImm16AndOperands(MCInst &Inst, unsigned N) const { 489303231Sdim assert(N == 1 && "Invalid number of operands!"); 490303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) 491303231Sdim Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff)); 492303231Sdim else 493303231Sdim assert(false && "Operand type not supported."); 494303231Sdim } 495303231Sdim 496303231Sdim void addHiImm16Operands(MCInst &Inst, unsigned N) const { 497303231Sdim assert(N == 1 && "Invalid number of operands!"); 498303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) 499303231Sdim Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16)); 500303231Sdim else if (isa<LanaiMCExpr>(getImm())) { 501303231Sdim#ifndef NDEBUG 502303231Sdim const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm()); 503360784Sdim assert(SymbolRefExpr && 504360784Sdim SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI); 505303231Sdim#endif 506303231Sdim Inst.addOperand(MCOperand::createExpr(getImm())); 507303231Sdim } else if (isa<MCBinaryExpr>(getImm())) { 508303231Sdim#ifndef NDEBUG 509303231Sdim const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm()); 510360784Sdim assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) && 511341825Sdim cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() == 512303231Sdim LanaiMCExpr::VK_Lanai_ABS_HI); 513303231Sdim#endif 514303231Sdim Inst.addOperand(MCOperand::createExpr(getImm())); 515303231Sdim } else 516303231Sdim assert(false && "Operand type not supported."); 517303231Sdim } 518303231Sdim 519303231Sdim void addHiImm16AndOperands(MCInst &Inst, unsigned N) const { 520303231Sdim assert(N == 1 && "Invalid number of operands!"); 521303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) 522303231Sdim Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16)); 523303231Sdim else 524303231Sdim assert(false && "Operand type not supported."); 525303231Sdim } 526303231Sdim 527303231Sdim void addLoImm21Operands(MCInst &Inst, unsigned N) const { 528303231Sdim assert(N == 1 && "Invalid number of operands!"); 529303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm())) 530303231Sdim Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff)); 531303231Sdim else if (isa<LanaiMCExpr>(getImm())) { 532303231Sdim#ifndef NDEBUG 533303231Sdim const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm()); 534303231Sdim assert(SymbolRefExpr && 535303231Sdim SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None); 536303231Sdim#endif 537303231Sdim Inst.addOperand(MCOperand::createExpr(getImm())); 538303231Sdim } else if (isa<MCSymbolRefExpr>(getImm())) { 539303231Sdim#ifndef NDEBUG 540303231Sdim const MCSymbolRefExpr *SymbolRefExpr = 541303231Sdim dyn_cast<MCSymbolRefExpr>(getImm()); 542303231Sdim assert(SymbolRefExpr && 543303231Sdim SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None); 544303231Sdim#endif 545303231Sdim Inst.addOperand(MCOperand::createExpr(getImm())); 546303231Sdim } else if (isa<MCBinaryExpr>(getImm())) { 547303231Sdim#ifndef NDEBUG 548303231Sdim const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm()); 549360784Sdim assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) && 550360784Sdim cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() == 551360784Sdim LanaiMCExpr::VK_Lanai_None); 552303231Sdim#endif 553303231Sdim Inst.addOperand(MCOperand::createExpr(getImm())); 554303231Sdim } else 555303231Sdim assert(false && "Operand type not supported."); 556303231Sdim } 557303231Sdim 558303231Sdim void print(raw_ostream &OS) const override { 559303231Sdim switch (Kind) { 560303231Sdim case IMMEDIATE: 561303231Sdim OS << "Imm: " << getImm() << "\n"; 562303231Sdim break; 563303231Sdim case TOKEN: 564303231Sdim OS << "Token: " << getToken() << "\n"; 565303231Sdim break; 566303231Sdim case REGISTER: 567303231Sdim OS << "Reg: %r" << getReg() << "\n"; 568303231Sdim break; 569303231Sdim case MEMORY_IMM: 570303231Sdim OS << "MemImm: " << *getMemOffset() << "\n"; 571303231Sdim break; 572303231Sdim case MEMORY_REG_IMM: 573303231Sdim OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n"; 574303231Sdim break; 575303231Sdim case MEMORY_REG_REG: 576303231Sdim assert(getMemOffset() == nullptr); 577303231Sdim OS << "MemRegReg: " << getMemBaseReg() << "+" 578303231Sdim << "%r" << getMemOffsetReg() << "\n"; 579303231Sdim break; 580303231Sdim } 581303231Sdim } 582303231Sdim 583303231Sdim static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) { 584360784Sdim auto Op = std::make_unique<LanaiOperand>(TOKEN); 585303231Sdim Op->Tok.Data = Str.data(); 586303231Sdim Op->Tok.Length = Str.size(); 587303231Sdim Op->StartLoc = Start; 588303231Sdim Op->EndLoc = Start; 589303231Sdim return Op; 590303231Sdim } 591303231Sdim 592303231Sdim static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start, 593303231Sdim SMLoc End) { 594360784Sdim auto Op = std::make_unique<LanaiOperand>(REGISTER); 595303231Sdim Op->Reg.RegNum = RegNum; 596303231Sdim Op->StartLoc = Start; 597303231Sdim Op->EndLoc = End; 598303231Sdim return Op; 599303231Sdim } 600303231Sdim 601303231Sdim static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value, 602303231Sdim SMLoc Start, SMLoc End) { 603360784Sdim auto Op = std::make_unique<LanaiOperand>(IMMEDIATE); 604303231Sdim Op->Imm.Value = Value; 605303231Sdim Op->StartLoc = Start; 606303231Sdim Op->EndLoc = End; 607303231Sdim return Op; 608303231Sdim } 609303231Sdim 610303231Sdim static std::unique_ptr<LanaiOperand> 611303231Sdim MorphToMemImm(std::unique_ptr<LanaiOperand> Op) { 612303231Sdim const MCExpr *Imm = Op->getImm(); 613303231Sdim Op->Kind = MEMORY_IMM; 614303231Sdim Op->Mem.BaseReg = 0; 615303231Sdim Op->Mem.AluOp = LPAC::ADD; 616303231Sdim Op->Mem.OffsetReg = 0; 617303231Sdim Op->Mem.Offset = Imm; 618303231Sdim return Op; 619303231Sdim } 620303231Sdim 621303231Sdim static std::unique_ptr<LanaiOperand> 622303231Sdim MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op, 623303231Sdim unsigned AluOp) { 624303231Sdim unsigned OffsetReg = Op->getReg(); 625303231Sdim Op->Kind = MEMORY_REG_REG; 626303231Sdim Op->Mem.BaseReg = BaseReg; 627303231Sdim Op->Mem.AluOp = AluOp; 628303231Sdim Op->Mem.OffsetReg = OffsetReg; 629303231Sdim Op->Mem.Offset = nullptr; 630303231Sdim return Op; 631303231Sdim } 632303231Sdim 633303231Sdim static std::unique_ptr<LanaiOperand> 634303231Sdim MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op, 635303231Sdim unsigned AluOp) { 636303231Sdim const MCExpr *Imm = Op->getImm(); 637303231Sdim Op->Kind = MEMORY_REG_IMM; 638303231Sdim Op->Mem.BaseReg = BaseReg; 639303231Sdim Op->Mem.AluOp = AluOp; 640303231Sdim Op->Mem.OffsetReg = 0; 641303231Sdim Op->Mem.Offset = Imm; 642303231Sdim return Op; 643303231Sdim } 644303231Sdim}; 645303231Sdim 646314564Sdim} // end anonymous namespace 647314564Sdim 648303231Sdimbool LanaiAsmParser::ParseDirective(AsmToken /*DirectiveId*/) { return true; } 649303231Sdim 650303231Sdimbool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode, 651303231Sdim OperandVector &Operands, 652303231Sdim MCStreamer &Out, 653303231Sdim uint64_t &ErrorInfo, 654303231Sdim bool MatchingInlineAsm) { 655303231Sdim MCInst Inst; 656303231Sdim SMLoc ErrorLoc; 657303231Sdim 658303231Sdim switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { 659303231Sdim case Match_Success: 660303231Sdim Out.EmitInstruction(Inst, SubtargetInfo); 661303231Sdim Opcode = Inst.getOpcode(); 662303231Sdim return false; 663303231Sdim case Match_MissingFeature: 664303231Sdim return Error(IdLoc, "Instruction use requires option to be enabled"); 665303231Sdim case Match_MnemonicFail: 666303231Sdim return Error(IdLoc, "Unrecognized instruction mnemonic"); 667303231Sdim case Match_InvalidOperand: { 668303231Sdim ErrorLoc = IdLoc; 669303231Sdim if (ErrorInfo != ~0U) { 670303231Sdim if (ErrorInfo >= Operands.size()) 671303231Sdim return Error(IdLoc, "Too few operands for instruction"); 672303231Sdim 673303231Sdim ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc(); 674303231Sdim if (ErrorLoc == SMLoc()) 675303231Sdim ErrorLoc = IdLoc; 676303231Sdim } 677303231Sdim return Error(ErrorLoc, "Invalid operand for instruction"); 678303231Sdim } 679303231Sdim default: 680303231Sdim break; 681303231Sdim } 682303231Sdim 683303231Sdim llvm_unreachable("Unknown match type detected!"); 684303231Sdim} 685303231Sdim 686303231Sdim// Both '%rN' and 'rN' are parsed as valid registers. This was done to remain 687303231Sdim// backwards compatible with GCC and the different ways inline assembly is 688303231Sdim// handled. 689303231Sdim// TODO: see if there isn't a better way to do this. 690303231Sdimstd::unique_ptr<LanaiOperand> LanaiAsmParser::parseRegister() { 691303231Sdim SMLoc Start = Parser.getTok().getLoc(); 692303231Sdim SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 693303231Sdim 694303231Sdim unsigned RegNum; 695303231Sdim // Eat the '%'. 696303231Sdim if (Lexer.getKind() == AsmToken::Percent) 697303231Sdim Parser.Lex(); 698303231Sdim if (Lexer.getKind() == AsmToken::Identifier) { 699303231Sdim RegNum = MatchRegisterName(Lexer.getTok().getIdentifier()); 700303231Sdim if (RegNum == 0) 701314564Sdim return nullptr; 702303231Sdim Parser.Lex(); // Eat identifier token 703303231Sdim return LanaiOperand::createReg(RegNum, Start, End); 704303231Sdim } 705314564Sdim return nullptr; 706303231Sdim} 707303231Sdim 708303231Sdimbool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc, 709303231Sdim SMLoc &EndLoc) { 710303231Sdim const AsmToken &Tok = getParser().getTok(); 711303231Sdim StartLoc = Tok.getLoc(); 712303231Sdim EndLoc = Tok.getEndLoc(); 713303231Sdim std::unique_ptr<LanaiOperand> Op = parseRegister(); 714303231Sdim if (Op != nullptr) 715303231Sdim RegNum = Op->getReg(); 716303231Sdim return (Op == nullptr); 717303231Sdim} 718303231Sdim 719303231Sdimstd::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() { 720303231Sdim SMLoc Start = Parser.getTok().getLoc(); 721303231Sdim SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 722314564Sdim const MCExpr *Res, *RHS = nullptr; 723303231Sdim LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None; 724303231Sdim 725303231Sdim if (Lexer.getKind() != AsmToken::Identifier) 726314564Sdim return nullptr; 727303231Sdim 728303231Sdim StringRef Identifier; 729303231Sdim if (Parser.parseIdentifier(Identifier)) 730314564Sdim return nullptr; 731303231Sdim 732303231Sdim // Check if identifier has a modifier 733303231Sdim if (Identifier.equals_lower("hi")) 734303231Sdim Kind = LanaiMCExpr::VK_Lanai_ABS_HI; 735303231Sdim else if (Identifier.equals_lower("lo")) 736303231Sdim Kind = LanaiMCExpr::VK_Lanai_ABS_LO; 737303231Sdim 738303231Sdim // If the identifier corresponds to a variant then extract the real 739303231Sdim // identifier. 740303231Sdim if (Kind != LanaiMCExpr::VK_Lanai_None) { 741303231Sdim if (Lexer.getKind() != AsmToken::LParen) { 742303231Sdim Error(Lexer.getLoc(), "Expected '('"); 743314564Sdim return nullptr; 744303231Sdim } 745303231Sdim Lexer.Lex(); // lex '(' 746303231Sdim 747303231Sdim // Parse identifier 748303231Sdim if (Parser.parseIdentifier(Identifier)) 749314564Sdim return nullptr; 750303231Sdim } 751303231Sdim 752303231Sdim // If addition parse the RHS. 753303231Sdim if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS)) 754314564Sdim return nullptr; 755303231Sdim 756303231Sdim // For variants parse the final ')' 757303231Sdim if (Kind != LanaiMCExpr::VK_Lanai_None) { 758303231Sdim if (Lexer.getKind() != AsmToken::RParen) { 759303231Sdim Error(Lexer.getLoc(), "Expected ')'"); 760314564Sdim return nullptr; 761303231Sdim } 762303231Sdim Lexer.Lex(); // lex ')' 763303231Sdim } 764303231Sdim 765303231Sdim End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 766303231Sdim MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 767303231Sdim const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext()); 768303231Sdim Res = LanaiMCExpr::create(Kind, Expr, getContext()); 769303231Sdim 770303231Sdim // Nest if this was an addition 771303231Sdim if (RHS) 772303231Sdim Res = MCBinaryExpr::createAdd(Res, RHS, getContext()); 773303231Sdim 774303231Sdim return LanaiOperand::createImm(Res, Start, End); 775303231Sdim} 776303231Sdim 777303231Sdimstd::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() { 778303231Sdim SMLoc Start = Parser.getTok().getLoc(); 779303231Sdim SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 780303231Sdim 781303231Sdim const MCExpr *ExprVal; 782303231Sdim switch (Lexer.getKind()) { 783303231Sdim case AsmToken::Identifier: 784303231Sdim return parseIdentifier(); 785303231Sdim case AsmToken::Plus: 786303231Sdim case AsmToken::Minus: 787303231Sdim case AsmToken::Integer: 788303231Sdim case AsmToken::Dot: 789303231Sdim if (!Parser.parseExpression(ExprVal)) 790303231Sdim return LanaiOperand::createImm(ExprVal, Start, End); 791321369Sdim LLVM_FALLTHROUGH; 792303231Sdim default: 793314564Sdim return nullptr; 794303231Sdim } 795303231Sdim} 796303231Sdim 797303231Sdimstatic unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) { 798303231Sdim if (PreOp) 799303231Sdim return LPAC::makePreOp(AluCode); 800303231Sdim if (PostOp) 801303231Sdim return LPAC::makePostOp(AluCode); 802303231Sdim return AluCode; 803303231Sdim} 804303231Sdim 805303231Sdimunsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) { 806303231Sdim StringRef IdString; 807303231Sdim Parser.parseIdentifier(IdString); 808303231Sdim unsigned AluCode = LPAC::stringToLanaiAluCode(IdString); 809303231Sdim if (AluCode == LPAC::UNKNOWN) { 810303231Sdim Error(Parser.getTok().getLoc(), "Can't parse ALU operator"); 811303231Sdim return 0; 812303231Sdim } 813303231Sdim return AluCode; 814303231Sdim} 815303231Sdim 816303231Sdimstatic int SizeForSuffix(StringRef T) { 817303231Sdim return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4); 818303231Sdim} 819303231Sdim 820303231Sdimbool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) { 821303231Sdim bool PreOrPost = false; 822303231Sdim if (Lexer.getKind() == Lexer.peekTok(true).getKind()) { 823303231Sdim PreOrPost = true; 824303231Sdim if (Lexer.is(AsmToken::Minus)) 825303231Sdim *OffsetValue = -SizeForSuffix(Type); 826303231Sdim else if (Lexer.is(AsmToken::Plus)) 827303231Sdim *OffsetValue = SizeForSuffix(Type); 828303231Sdim else 829303231Sdim return false; 830303231Sdim 831303231Sdim // Eat the '-' '-' or '+' '+' 832303231Sdim Parser.Lex(); 833303231Sdim Parser.Lex(); 834303231Sdim } else if (Lexer.is(AsmToken::Star)) { 835303231Sdim Parser.Lex(); // Eat the '*' 836303231Sdim PreOrPost = true; 837303231Sdim } 838303231Sdim 839303231Sdim return PreOrPost; 840303231Sdim} 841303231Sdim 842303231Sdimbool shouldBeSls(const LanaiOperand &Op) { 843303231Sdim // The instruction should be encoded as an SLS if the constant is word 844303231Sdim // aligned and will fit in 21 bits 845303231Sdim if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) { 846303231Sdim int64_t Value = ConstExpr->getValue(); 847303231Sdim return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff); 848303231Sdim } 849303231Sdim // The instruction should be encoded as an SLS if the operand is a symbolic 850303231Sdim // reference with no variant. 851303231Sdim if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm())) 852303231Sdim return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None; 853303231Sdim // The instruction should be encoded as an SLS if the operand is a binary 854303231Sdim // expression with the left-hand side being a symbolic reference with no 855303231Sdim // variant. 856303231Sdim if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) { 857303231Sdim const LanaiMCExpr *LHSSymbolRefExpr = 858303231Sdim dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()); 859303231Sdim return (LHSSymbolRefExpr && 860303231Sdim LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None); 861303231Sdim } 862303231Sdim return false; 863303231Sdim} 864303231Sdim 865303231Sdim// Matches memory operand. Returns true if error encountered. 866314564SdimOperandMatchResultTy 867303231SdimLanaiAsmParser::parseMemoryOperand(OperandVector &Operands) { 868303231Sdim // Try to match a memory operand. 869303231Sdim // The memory operands are of the form: 870303231Sdim // (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or 871303231Sdim // ^ 872303231Sdim // (2) '[' '*'? Register '*'? AluOperator Register ']' 873303231Sdim // ^ 874303231Sdim // (3) '[' '--'|'++' Register '--'|'++' ']' 875303231Sdim // 876303231Sdim // (4) '[' Immediate ']' (for SLS) 877303231Sdim 878303231Sdim // Store the type for use in parsing pre/post increment/decrement operators 879303231Sdim StringRef Type; 880303231Sdim if (Operands[0]->isToken()) 881303231Sdim Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken(); 882303231Sdim 883303231Sdim // Use 0 if no offset given 884303231Sdim int OffsetValue = 0; 885303231Sdim unsigned BaseReg = 0; 886303231Sdim unsigned AluOp = LPAC::ADD; 887303231Sdim bool PostOp = false, PreOp = false; 888303231Sdim 889303231Sdim // Try to parse the offset 890303231Sdim std::unique_ptr<LanaiOperand> Op = parseRegister(); 891303231Sdim if (!Op) 892303231Sdim Op = parseImmediate(); 893303231Sdim 894303231Sdim // Only continue if next token is '[' 895303231Sdim if (Lexer.isNot(AsmToken::LBrac)) { 896303231Sdim if (!Op) 897303231Sdim return MatchOperand_NoMatch; 898303231Sdim 899303231Sdim // The start of this custom parsing overlaps with register/immediate so 900303231Sdim // consider this as a successful match of an operand of that type as the 901303231Sdim // token stream can't be rewound to allow them to match separately. 902303231Sdim Operands.push_back(std::move(Op)); 903303231Sdim return MatchOperand_Success; 904303231Sdim } 905303231Sdim 906303231Sdim Parser.Lex(); // Eat the '['. 907303231Sdim std::unique_ptr<LanaiOperand> Offset = nullptr; 908303231Sdim if (Op) 909303231Sdim Offset.swap(Op); 910303231Sdim 911303231Sdim // Determine if a pre operation 912303231Sdim PreOp = parsePrePost(Type, &OffsetValue); 913303231Sdim 914303231Sdim Op = parseRegister(); 915303231Sdim if (!Op) { 916303231Sdim if (!Offset) { 917303231Sdim if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) { 918303231Sdim Parser.Lex(); // Eat the ']' 919303231Sdim 920303231Sdim // Memory address operations aligned to word boundary are encoded as 921303231Sdim // SLS, the rest as RM. 922303231Sdim if (shouldBeSls(*Op)) { 923303231Sdim Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op))); 924303231Sdim } else { 925303231Sdim if (!Op->isLoImm16Signed()) { 926303231Sdim Error(Parser.getTok().getLoc(), 927303231Sdim "Memory address is not word " 928303231Sdim "aligned and larger than class RM can handle"); 929303231Sdim return MatchOperand_ParseFail; 930303231Sdim } 931303231Sdim Operands.push_back(LanaiOperand::MorphToMemRegImm( 932303231Sdim Lanai::R0, std::move(Op), LPAC::ADD)); 933303231Sdim } 934303231Sdim return MatchOperand_Success; 935303231Sdim } 936303231Sdim } 937303231Sdim 938303231Sdim Error(Parser.getTok().getLoc(), 939303231Sdim "Unknown operand, expected register or immediate"); 940303231Sdim return MatchOperand_ParseFail; 941303231Sdim } 942303231Sdim BaseReg = Op->getReg(); 943303231Sdim 944303231Sdim // Determine if a post operation 945303231Sdim if (!PreOp) 946303231Sdim PostOp = parsePrePost(Type, &OffsetValue); 947303231Sdim 948303231Sdim // If ] match form (1) else match form (2) 949303231Sdim if (Lexer.is(AsmToken::RBrac)) { 950303231Sdim Parser.Lex(); // Eat the ']'. 951303231Sdim if (!Offset) { 952303231Sdim SMLoc Start = Parser.getTok().getLoc(); 953303231Sdim SMLoc End = 954303231Sdim SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 955303231Sdim const MCConstantExpr *OffsetConstExpr = 956303231Sdim MCConstantExpr::create(OffsetValue, getContext()); 957303231Sdim Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End); 958303231Sdim } 959303231Sdim } else { 960303231Sdim if (Offset || OffsetValue != 0) { 961303231Sdim Error(Parser.getTok().getLoc(), "Expected ']'"); 962303231Sdim return MatchOperand_ParseFail; 963303231Sdim } 964303231Sdim 965303231Sdim // Parse operator 966303231Sdim AluOp = parseAluOperator(PreOp, PostOp); 967303231Sdim 968303231Sdim // Second form requires offset register 969303231Sdim Offset = parseRegister(); 970303231Sdim if (!BaseReg || Lexer.isNot(AsmToken::RBrac)) { 971303231Sdim Error(Parser.getTok().getLoc(), "Expected ']'"); 972303231Sdim return MatchOperand_ParseFail; 973303231Sdim } 974303231Sdim Parser.Lex(); // Eat the ']'. 975303231Sdim } 976303231Sdim 977303231Sdim // First form has addition as operator. Add pre- or post-op indicator as 978303231Sdim // needed. 979303231Sdim AluOp = AluWithPrePost(AluOp, PreOp, PostOp); 980303231Sdim 981303231Sdim // Ensure immediate offset is not too large 982303231Sdim if (Offset->isImm() && !Offset->isLoImm16Signed()) { 983303231Sdim Error(Parser.getTok().getLoc(), 984303231Sdim "Memory address is not word " 985303231Sdim "aligned and larger than class RM can handle"); 986303231Sdim return MatchOperand_ParseFail; 987303231Sdim } 988303231Sdim 989303231Sdim Operands.push_back( 990303231Sdim Offset->isImm() 991303231Sdim ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp) 992303231Sdim : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp)); 993303231Sdim 994303231Sdim return MatchOperand_Success; 995303231Sdim} 996303231Sdim 997303231Sdim// Looks at a token type and creates the relevant operand from this 998303231Sdim// information, adding to operands. 999303231Sdim// If operand was parsed, returns false, else true. 1000314564SdimOperandMatchResultTy 1001303231SdimLanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) { 1002303231Sdim // Check if the current operand has a custom associated parser, if so, try to 1003303231Sdim // custom parse the operand, or fallback to the general approach. 1004303231Sdim OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic); 1005303231Sdim 1006303231Sdim if (Result == MatchOperand_Success) 1007303231Sdim return Result; 1008303231Sdim if (Result == MatchOperand_ParseFail) { 1009303231Sdim Parser.eatToEndOfStatement(); 1010303231Sdim return Result; 1011303231Sdim } 1012303231Sdim 1013303231Sdim // Attempt to parse token as register 1014303231Sdim std::unique_ptr<LanaiOperand> Op = parseRegister(); 1015303231Sdim 1016303231Sdim // Attempt to parse token as immediate 1017303231Sdim if (!Op) 1018303231Sdim Op = parseImmediate(); 1019303231Sdim 1020303231Sdim // If the token could not be parsed then fail 1021303231Sdim if (!Op) { 1022303231Sdim Error(Parser.getTok().getLoc(), "Unknown operand"); 1023303231Sdim Parser.eatToEndOfStatement(); 1024303231Sdim return MatchOperand_ParseFail; 1025303231Sdim } 1026303231Sdim 1027303231Sdim // Push back parsed operand into list of operands 1028303231Sdim Operands->push_back(std::move(Op)); 1029303231Sdim 1030303231Sdim return MatchOperand_Success; 1031303231Sdim} 1032303231Sdim 1033303231Sdim// Split the mnemonic into ASM operand, conditional code and instruction 1034303231Sdim// qualifier (half-word, byte). 1035303231SdimStringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc, 1036303231Sdim OperandVector *Operands) { 1037303231Sdim size_t Next = Name.find('.'); 1038303231Sdim 1039303231Sdim StringRef Mnemonic = Name; 1040303231Sdim 1041303231Sdim bool IsBRR = false; 1042303231Sdim if (Name.endswith(".r")) { 1043303231Sdim Mnemonic = Name.substr(0, Name.size() - 2); 1044303231Sdim IsBRR = true; 1045303231Sdim } 1046303231Sdim 1047303231Sdim // Match b?? and s?? (BR, BRR, and SCC instruction classes). 1048303231Sdim if (Mnemonic[0] == 'b' || 1049303231Sdim (Mnemonic[0] == 's' && !Mnemonic.startswith("sel") && 1050303231Sdim !Mnemonic.startswith("st"))) { 1051303231Sdim // Parse instructions with a conditional code. For example, 'bne' is 1052303231Sdim // converted into two operands 'b' and 'ne'. 1053303231Sdim LPCC::CondCode CondCode = 1054303231Sdim LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next)); 1055303231Sdim if (CondCode != LPCC::UNKNOWN) { 1056303231Sdim Mnemonic = Mnemonic.slice(0, 1); 1057303231Sdim Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc)); 1058303231Sdim Operands->push_back(LanaiOperand::createImm( 1059303231Sdim MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc)); 1060303231Sdim if (IsBRR) { 1061303231Sdim Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc)); 1062303231Sdim } 1063303231Sdim return Mnemonic; 1064303231Sdim } 1065303231Sdim } 1066303231Sdim 1067303231Sdim // Parse other instructions with condition codes (RR instructions). 1068303231Sdim // We ignore .f here and assume they are flag-setting operations, not 1069303231Sdim // conditional codes (except for select instructions where flag-setting 1070303231Sdim // variants are not yet implemented). 1071303231Sdim if (Mnemonic.startswith("sel") || 1072303231Sdim (!Mnemonic.endswith(".f") && !Mnemonic.startswith("st"))) { 1073303231Sdim LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic); 1074303231Sdim if (CondCode != LPCC::UNKNOWN) { 1075303231Sdim size_t Next = Mnemonic.rfind('.', Name.size()); 1076303231Sdim // 'sel' doesn't use a predicate operand whose printer adds the period, 1077303231Sdim // but instead has the period as part of the identifier (i.e., 'sel.' is 1078303231Sdim // expected by the generated matcher). If the mnemonic starts with 'sel' 1079303231Sdim // then include the period as part of the mnemonic, else don't include it 1080303231Sdim // as part of the mnemonic. 1081303231Sdim if (Mnemonic.startswith("sel")) { 1082303231Sdim Mnemonic = Mnemonic.substr(0, Next + 1); 1083303231Sdim } else { 1084303231Sdim Mnemonic = Mnemonic.substr(0, Next); 1085303231Sdim } 1086303231Sdim Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc)); 1087303231Sdim Operands->push_back(LanaiOperand::createImm( 1088303231Sdim MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc)); 1089303231Sdim return Mnemonic; 1090303231Sdim } 1091303231Sdim } 1092303231Sdim 1093303231Sdim Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc)); 1094303231Sdim if (IsBRR) { 1095303231Sdim Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc)); 1096303231Sdim } 1097303231Sdim 1098303231Sdim return Mnemonic; 1099303231Sdim} 1100303231Sdim 1101321369Sdimstatic bool IsMemoryAssignmentError(const OperandVector &Operands) { 1102303231Sdim // Detects if a memory operation has an erroneous base register modification. 1103303231Sdim // Memory operations are detected by matching the types of operands. 1104303231Sdim // 1105303231Sdim // TODO: This test is focussed on one specific instance (ld/st). 1106303231Sdim // Extend it to handle more cases or be more robust. 1107303231Sdim bool Modifies = false; 1108303231Sdim 1109303231Sdim int Offset = 0; 1110303231Sdim 1111303231Sdim if (Operands.size() < 5) 1112303231Sdim return false; 1113303231Sdim else if (Operands[0]->isToken() && Operands[1]->isReg() && 1114303231Sdim Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg()) 1115303231Sdim Offset = 0; 1116303231Sdim else if (Operands[0]->isToken() && Operands[1]->isToken() && 1117303231Sdim Operands[2]->isReg() && Operands[3]->isImm() && 1118303231Sdim Operands[4]->isImm() && Operands[5]->isReg()) 1119303231Sdim Offset = 1; 1120303231Sdim else 1121303231Sdim return false; 1122303231Sdim 1123303231Sdim int PossibleAluOpIdx = Offset + 3; 1124303231Sdim int PossibleBaseIdx = Offset + 1; 1125303231Sdim int PossibleDestIdx = Offset + 4; 1126303231Sdim if (LanaiOperand *PossibleAluOp = 1127303231Sdim static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get())) 1128303231Sdim if (PossibleAluOp->isImm()) 1129303231Sdim if (const MCConstantExpr *ConstExpr = 1130303231Sdim dyn_cast<MCConstantExpr>(PossibleAluOp->getImm())) 1131303231Sdim Modifies = LPAC::modifiesOp(ConstExpr->getValue()); 1132303231Sdim return Modifies && Operands[PossibleBaseIdx]->isReg() && 1133303231Sdim Operands[PossibleDestIdx]->isReg() && 1134303231Sdim Operands[PossibleBaseIdx]->getReg() == 1135303231Sdim Operands[PossibleDestIdx]->getReg(); 1136303231Sdim} 1137303231Sdim 1138303231Sdimstatic bool IsRegister(const MCParsedAsmOperand &op) { 1139303231Sdim return static_cast<const LanaiOperand &>(op).isReg(); 1140303231Sdim} 1141303231Sdim 1142303231Sdimstatic bool MaybePredicatedInst(const OperandVector &Operands) { 1143303231Sdim if (Operands.size() < 4 || !IsRegister(*Operands[1]) || 1144303231Sdim !IsRegister(*Operands[2])) 1145303231Sdim return false; 1146303231Sdim return StringSwitch<bool>( 1147303231Sdim static_cast<const LanaiOperand &>(*Operands[0]).getToken()) 1148303231Sdim .StartsWith("addc", true) 1149303231Sdim .StartsWith("add", true) 1150303231Sdim .StartsWith("and", true) 1151303231Sdim .StartsWith("sh", true) 1152303231Sdim .StartsWith("subb", true) 1153303231Sdim .StartsWith("sub", true) 1154303231Sdim .StartsWith("or", true) 1155303231Sdim .StartsWith("xor", true) 1156303231Sdim .Default(false); 1157303231Sdim} 1158303231Sdim 1159303231Sdimbool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/, 1160303231Sdim StringRef Name, SMLoc NameLoc, 1161303231Sdim OperandVector &Operands) { 1162303231Sdim // First operand is token for instruction 1163303231Sdim StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands); 1164303231Sdim 1165303231Sdim // If there are no more operands, then finish 1166303231Sdim if (Lexer.is(AsmToken::EndOfStatement)) 1167303231Sdim return false; 1168303231Sdim 1169303231Sdim // Parse first operand 1170303231Sdim if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success) 1171303231Sdim return true; 1172303231Sdim 1173303231Sdim // If it is a st instruction with one 1 operand then it is a "store true". 1174303231Sdim // Transform <"st"> to <"s">, <LPCC:ICC_T> 1175303231Sdim if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" && 1176303231Sdim Operands.size() == 2) { 1177303231Sdim Operands.erase(Operands.begin(), Operands.begin() + 1); 1178303231Sdim Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc)); 1179303231Sdim Operands.insert(Operands.begin() + 1, 1180303231Sdim LanaiOperand::createImm( 1181303231Sdim MCConstantExpr::create(LPCC::ICC_T, getContext()), 1182303231Sdim NameLoc, NameLoc)); 1183303231Sdim } 1184303231Sdim 1185303231Sdim // If the instruction is a bt instruction with 1 operand (in assembly) then it 1186303231Sdim // is an unconditional branch instruction and the first two elements of 1187303231Sdim // operands need to be merged. 1188303231Sdim if (Lexer.is(AsmToken::EndOfStatement) && Name.startswith("bt") && 1189303231Sdim Operands.size() == 3) { 1190303231Sdim Operands.erase(Operands.begin(), Operands.begin() + 2); 1191303231Sdim Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc)); 1192303231Sdim } 1193303231Sdim 1194303231Sdim // Parse until end of statement, consuming commas between operands 1195303231Sdim while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) { 1196303231Sdim // Consume comma token 1197303231Sdim Lex(); 1198303231Sdim 1199303231Sdim // Parse next operand 1200303231Sdim if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success) 1201303231Sdim return true; 1202303231Sdim } 1203303231Sdim 1204303231Sdim if (IsMemoryAssignmentError(Operands)) { 1205303231Sdim Error(Parser.getTok().getLoc(), 1206303231Sdim "the destination register can't equal the base register in an " 1207303231Sdim "instruction that modifies the base register."); 1208303231Sdim return true; 1209303231Sdim } 1210303231Sdim 1211303231Sdim // Insert always true operand for instruction that may be predicated but 1212303231Sdim // are not. Currently the autogenerated parser always expects a predicate. 1213303231Sdim if (MaybePredicatedInst(Operands)) { 1214303231Sdim Operands.insert(Operands.begin() + 1, 1215303231Sdim LanaiOperand::createImm( 1216303231Sdim MCConstantExpr::create(LPCC::ICC_T, getContext()), 1217303231Sdim NameLoc, NameLoc)); 1218303231Sdim } 1219303231Sdim 1220303231Sdim return false; 1221303231Sdim} 1222303231Sdim 1223303231Sdim#define GET_REGISTER_MATCHER 1224303231Sdim#define GET_MATCHER_IMPLEMENTATION 1225303231Sdim#include "LanaiGenAsmMatcher.inc" 1226303231Sdim 1227360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser() { 1228314564Sdim RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget()); 1229303231Sdim} 1230