Index: lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp =================================================================== --- lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp +++ lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp @@ -99,6 +99,8 @@ OperandMatchResultTy parseJumpTarget(OperandVector &Operands); + bool parseRelocOperand(OperandVector &Operands); + bool parseOperand(OperandVector &Operands, StringRef Mnemonic); int matchCPURegisterName(StringRef Symbol); @@ -670,6 +672,44 @@ return MatchOperand_Success; } +bool NDS32AsmParser::parseRelocOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + DEBUG(dbgs() << "parseRelocOperand\n"); + const AsmToken &Tok = Parser.getTok(); // Get next token, operation. + if (Tok.isNot(AsmToken::Identifier)) + return true; + + SMLoc S = Parser.getTok().getLoc(); + std::string Str = Tok.getIdentifier(); + Parser.Lex(); // Eat the identifier. + // Now make an expression from the rest of the operand. + const MCExpr *IdVal = nullptr; + SMLoc E; + + if (getLexer().getKind() == AsmToken::LParen) { + Parser.Lex(); // Eat the '(' token. + if (getParser().parseParenExpression(IdVal, E)) + return true; + + while (getLexer().getKind() == AsmToken::RParen) + Parser.Lex(); // Eat the ')' token. + } else + return true; // Parenthesis must follow the relocation operand. + + NDS32MCExpr::NDS32ExprKind Kind = + StringSwitch(Str) + .Case("hi20", NDS32MCExpr::MEK_HI) + .Case("lo12", NDS32MCExpr::MEK_LO) + .Default(NDS32MCExpr::MEK_None); + + assert(Kind != NDS32MCExpr::MEK_None); + + IdVal = NDS32MCExpr::create(Kind, IdVal, getContext()); + Operands.push_back(NDS32Operand::CreateImm(IdVal, S, E, *this)); + + return false; +} + bool NDS32AsmParser:: ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { @@ -787,6 +827,9 @@ if (parseAnyRegister(Operands) != MatchOperand_NoMatch) return false; } + case AsmToken::Identifier: + DEBUG(dbgs() << "parse Identifier\n"); + return parseRelocOperand(Operands); case AsmToken::Minus: case AsmToken::Plus: case AsmToken::Integer: Index: lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.cpp =================================================================== --- lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.cpp +++ lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.cpp @@ -111,6 +111,47 @@ unsigned NDS32MCCodeEmitter:: getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + int64_t Res; + + if (Expr->evaluateAsAbsolute(Res)) + return Res; + + MCExpr::ExprKind Kind = Expr->getKind(); + + if (Kind == MCExpr::Target) { + const NDS32MCExpr *NDS32Expr = cast(Expr); + + NDS32::Fixups FixupKind = NDS32::Fixups(0); + switch (NDS32Expr->getKind()) { + case NDS32MCExpr::MEK_None: + case NDS32MCExpr::MEK_Special: + llvm_unreachable("Unhandled fixup kind!"); + break; + case NDS32MCExpr::MEK_HI: + FixupKind = NDS32::fixup_NDS32_HI20_RELA; + break; + case NDS32MCExpr::MEK_LO: + FixupKind = NDS32::fixup_NDS32_LO12S0_RELA; + break; + } + Fixups.push_back(MCFixup::create(0, NDS32Expr, MCFixupKind(FixupKind))); + return 0; + } + + if (Kind == MCExpr::SymbolRef) { + NDS32::Fixups FixupKind = NDS32::Fixups(0); + + switch(cast(Expr)->getKind()) { + default: llvm_unreachable("Unknown fixup kind!"); + break; + case MCSymbolRefExpr::VK_None: + FixupKind = NDS32::fixup_NDS32_32; + break; + } // switch + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); + return 0; + } + return 0; } Index: lib/Target/NDS32/MCTargetDesc/NDS32MCExpr.cpp =================================================================== --- lib/Target/NDS32/MCTargetDesc/NDS32MCExpr.cpp +++ lib/Target/NDS32/MCTargetDesc/NDS32MCExpr.cpp @@ -60,7 +60,32 @@ NDS32MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { - return false; + if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) + return false; + + if (Res.getRefKind() != MCSymbolRefExpr::VK_None) + return false; + + if (Res.isAbsolute() && Fixup == nullptr) { + int64_t AbsVal = Res.getConstant(); + switch (Kind) { + case MEK_None: + case MEK_Special: + llvm_unreachable("MEK_None and MEK_Special are invalid"); + case MEK_HI: + AbsVal = SignExtend64<20>(AbsVal >> 12); + break; + case MEK_LO: + AbsVal = SignExtend64<12>(AbsVal & 0xfff); + break; + } + Res = MCValue::get(AbsVal); + return true; + } + + Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), + getKind()); + return true; } void NDS32MCExpr::visitUsedExpr(MCStreamer &Streamer) const { Index: test/MC/NDS32/elf-reloc.s =================================================================== --- /dev/null +++ test/MC/NDS32/elf-reloc.s @@ -0,0 +1,16 @@ +! RUN: llvm-mc -triple=nds32 -filetype=obj %s -o - | \ +! RUN: llvm-readobj -r | FileCheck -check-prefix=OBJ %s + + sethi $r1, hi20(.L.str) + ori $r1, $r1, lo12(.L.str) + + .section .rodata,"a",%progbits +.L.str: + .asciz "@null\n" + +! OBJ: Relocations [ +! OBJ: Section {{.*}} .rela.text { +! OBJ-NEXT: 0x{{[0-9,A-F]+}} R_NDS32_HI20_RELA .rodata 0x0 +! OBJ-NEXT: 0x{{[0-9,A-F]+}} R_NDS32_LO12S0_RELA .rodata 0x0 +! OBJ: } +! OBJ: ] Index: test/MC/NDS32/move.s =================================================================== --- /dev/null +++ test/MC/NDS32/move.s @@ -0,0 +1,13 @@ +! RUN: llvm-mc -triple nds32 -filetype=obj -o %t %s +! RUN: llvm-objdump -d -r -triple nds32 %t | FileCheck %s +move: + movi $r2, -20 + sethi $r1, hi20(12345678) + ori $r1, $r1, lo12(12345678) + mov55 $r23, $r24 + movi55 $r21, -12 +! CHECK: 44 2f ff ec movi $r2, -20 +! CHECK: 46 10 0b c6 sethi $r1, 3014 +! CHECK: 58 10 81 4e ori $r1, $r1, 334 +! CHECK: 82 f8 mov55 $r23, $r24 +! CHECK: 86 b4 movi55 $r21, -12