Index: lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp =================================================================== --- lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp +++ lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp @@ -101,6 +101,8 @@ bool parseRelocOperand(OperandVector &Operands); + bool parseMemory(OperandVector &Operands); + bool parseOperand(OperandVector &Operands, StringRef Mnemonic); int matchCPURegisterName(StringRef Symbol); @@ -266,33 +268,71 @@ } void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + addRegOperands (Inst, N); } void addAddrRegShiftOperands(MCInst &Inst, unsigned N) const { + assert(N == 3 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); + Inst.addOperand(MCOperand::createImm(Memory.ShiftImm)); } void addAddrImm15sWordOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrImm15sHalfOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrImm15sByteOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrImm3uWordOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrImm3uHalfOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrImm3uByteOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrFPImm7uWordOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrSPImm7uWordOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(NDS32::SP)); + Inst.addOperand(MCOperand::createImm(Val)); } void addRegListOperands(MCInst &Inst, unsigned N) const { @@ -338,69 +378,111 @@ return isConstantImm() ? isUIntN(20, getConstantImm()) : isImm(); } bool isMemNoOffset() const { - return false; + if (!isMem()) return false; + // No offset of any kind. + return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr; } // [Reg + Reg << sv], sv could be 0, 1, 2, 3 bool isAddrRegShift() const { - return false; + if (!isMem()) return false; + if (Memory.OffsetImm != nullptr) return false; + if (Memory.ShiftImm > 3) return false; + return true; } // [Reg + imm15s << 2] bool isAddrImm15sWord() const { - return false; + if (!isMem()) return false; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + if (Memory.isMinusOffset) Val = -Val; + return isIntN(15 + 2, Val) && (Val % 4 == 0); } // [Reg + imm15s << 1] bool isAddrImm15sHalf() const { - return false; + if (!isMem()) return false; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + if (Memory.isMinusOffset) Val = -Val; + return isIntN(15 + 1, Val) && (Val % 2 == 0); } // [Reg + imm15s] bool isAddrImm15sByte() const { - return false; + if (!isMem()) return false; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + if (Memory.isMinusOffset) Val = -Val; + return isIntN(15, Val); } // [Reg + imm3u << 2] bool isAddrImm3uWord() const { - return false; + if (!isMem()) return false; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + return isUIntN(3 + 2, Val) && (Val % 4 == 0); } // [Reg + imm3u << 1] bool isAddrImm3uHalf() const { - return false; + if (!isMem()) return false; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + return isUIntN(3 + 1, Val) && (Val % 2 == 0); } // [Reg + imm3u] bool isAddrImm3uByte() const { - return false; + if (!isMem()) return false; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + return isUIntN(3, Val); } // [FP + imm7u << 2] bool isAddrFPImm7uWord() const { - return false; + if (!isMem()) return false; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + return isUIntN(7 + 2, Val) && (Val % 4 == 0); } // [SP + imm7u << 2] bool isAddrSPImm7uWord() const { - return false; + if (!isMem()) return false; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + return isUIntN(7 + 2, Val) && (Val % 4 == 0); } // imm15s << 2 bool isOffsetImm15sWord() const { - return false; + return isConstantImm() && isIntN(15 + 2, getConstantImm()) && + (getConstantImm() % 4 == 0); } // imm15s << 1 bool isOffsetImm15sHalf() const { - return false; + return isConstantImm() && isIntN(15 + 1, getConstantImm()) && + (getConstantImm() % 2 == 0); } // imm15s bool isOffsetImm15sByte() const { - return false; + return isConstantImm() && isIntN(15, getConstantImm()); } bool isMemRegOffset() const { - return false; + return isReg(); } void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); } void addOffsetImm15sWordOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createImm(getConstantImm())); } void addOffsetImm15sHalfOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createImm(getConstantImm())); } void addOffsetImm15sByteOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createImm(getConstantImm())); } StringRef getToken() const { @@ -464,6 +546,15 @@ CreateMem(unsigned BaseRegNum, const MCConstantExpr *OffsetImm, unsigned OffsetRegNum, unsigned ShiftImm, bool isMinusOffset, SMLoc S, SMLoc E, NDS32AsmParser &Parser) { + auto Op = make_unique(k_Memory, Parser); + Op->Memory.BaseRegNum = BaseRegNum; + Op->Memory.OffsetImm = OffsetImm; + Op->Memory.OffsetRegNum = OffsetRegNum; + Op->Memory.ShiftImm = ShiftImm; + Op->Memory.isMinusOffset = isMinusOffset; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; } static std::unique_ptr @@ -710,6 +801,145 @@ return false; } +// Parse an NDS32 memory expression, return false if successful else return +// true or an error. The first token must be a '[' when called. +bool NDS32AsmParser::parseMemory(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + SMLoc S, E; + bool isMinusOffset = false; + int BaseRegNum = -1; + + DEBUG(dbgs() << "ParseMemory\n"); + + assert(Parser.getTok().is(AsmToken::LBrac) && + "Token is not a Left Bracket"); + S = Parser.getTok().getLoc(); + Parser.Lex(); // Eat left bracket token. + + if (Parser.getTok().is(AsmToken::Dollar)) { + Parser.Lex(); // Eat the Dollar. + DEBUG(dbgs() << "Eat $ \n"); + + const AsmToken &BaseRegTok = Parser.getTok(); + BaseRegNum = tryParseRegister(); + if (BaseRegNum == -1) + return Error(BaseRegTok.getLoc(), "register expected"); + + DEBUG(dbgs() << "BaseRegNum = " << BaseRegNum << "\n"); + } + + // The next token must either be a plus or a closing bracket. + const AsmToken &Tok = Parser.getTok(); + if (!Tok.is(AsmToken::Plus) && + !Tok.is(AsmToken::RBrac)) + return Error(Tok.getLoc(), "malformed memory operand"); + + // parsing [Reg] + if (Tok.is(AsmToken::RBrac)) { + E = Tok.getEndLoc(); + Parser.Lex(); // Eat right bracket token. + + Operands.push_back(NDS32Operand::CreateMem(BaseRegNum, nullptr, 0, 0, + isMinusOffset, S, E, *this)); + return false; + } + + assert(Tok.is(AsmToken::Plus) && "Lost Plus in memory operand?!"); + + if (Tok.is(AsmToken::Plus)) { + DEBUG(dbgs() << "Eat + \n"); + Parser.Lex(); // Eat the Plus. + } + + if (Tok.is(AsmToken::LParen)) { + DEBUG(dbgs() << "Eat ( \n"); + Parser.Lex(); // Eat the LParen. + } + + if (Tok.is(AsmToken::Minus)) { + DEBUG(dbgs() << "Eat - \n"); + Parser.Lex(); // Eat the Minus. + isMinusOffset = true; + } + + // parsing [Reg + Imm] + if (Parser.getTok().is(AsmToken::Integer)) { + E = Parser.getTok().getLoc(); + + const MCExpr *Offset; + if (getParser().parseExpression(Offset)) + return true; + + // The expression has to be a constant. Memory references with relocations + // don't come through here, as they use the