Index: lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp =================================================================== --- lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp +++ lib/Target/NDS32/AsmParser/NDS32AsmParser.cpp @@ -97,6 +97,8 @@ OperandMatchResultTy parseAnyRegister(OperandVector &Operands); + OperandMatchResultTy parseJumpTarget(OperandVector &Operands); + bool parseOperand(OperandVector &, StringRef Mnemonic); int matchCPURegisterName(StringRef Symbol); @@ -646,6 +648,28 @@ return RegNum; } +OperandMatchResultTy +NDS32AsmParser::parseJumpTarget(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + DEBUG(dbgs() << "parseJumpTarget\n"); + + SMLoc S = getLexer().getLoc(); + + // Integers and expressions are acceptable + OperandMatchResultTy ResTy = parseImm(Operands); + if (ResTy != MatchOperand_NoMatch) + return ResTy; + + const MCExpr *Expr = nullptr; + if (Parser.parseExpression(Expr)) { + // We have no way of knowing if a symbol was consumed so we must ParseFail + return MatchOperand_ParseFail; + } + Operands.push_back( + NDS32Operand::CreateImm(Expr, S, getLexer().getLoc(), *this)); + return MatchOperand_Success; +} + bool NDS32AsmParser:: ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { @@ -743,6 +767,17 @@ MCAsmParser &Parser = getParser(); DEBUG(dbgs() << "parseOperand\n"); + // Check if the current operand has a custom associated parser, if so, try to + // custom parse the operand, or fallback to the general approach. + OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); + if (ResTy == MatchOperand_Success) + return false; + // If there wasn't a custom match, try the generic matcher below. Otherwise, + // there was a match, but an error occurred, in which case, just return that + // the operand parsing failed. + if (ResTy == MatchOperand_ParseFail) + return true; + switch (getLexer().getKind()) { default: Error(Parser.getTok().getLoc(), "unexpected token in operand"); Index: lib/Target/NDS32/Disassembler/NDS32Disassembler.cpp =================================================================== --- lib/Target/NDS32/Disassembler/NDS32Disassembler.cpp +++ lib/Target/NDS32/Disassembler/NDS32Disassembler.cpp @@ -209,6 +209,8 @@ unsigned Offset, uint64_t Address, const void *Decoder) { + int32_t BranchOffset = (SignExtend32<24>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } @@ -216,6 +218,8 @@ unsigned Offset, uint64_t Address, const void *Decoder) { + int32_t BranchOffset = (SignExtend32<14>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } @@ -223,6 +227,8 @@ unsigned Offset, uint64_t Address, const void *Decoder) { + int32_t BranchOffset = (SignExtend32<16>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } @@ -230,6 +236,8 @@ unsigned Offset, uint64_t Address, const void *Decoder) { + int32_t BranchOffset = (SignExtend32<8>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } Index: lib/Target/NDS32/MCTargetDesc/NDS32AsmBackend.cpp =================================================================== --- lib/Target/NDS32/MCTargetDesc/NDS32AsmBackend.cpp +++ lib/Target/NDS32/MCTargetDesc/NDS32AsmBackend.cpp @@ -36,7 +36,48 @@ // Prepare value for the target space for it static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, MCContext *Ctx = nullptr) { - return 0; + unsigned Kind = Fixup.getKind(); + + switch (Kind) { + default: + return 0; + case FK_Data_1: + case FK_Data_2: + case FK_Data_4: + case FK_SecRel_2: + case FK_SecRel_4: + break; + case NDS32::fixup_NDS32_9_32BIT_INSN_PCREL_RELA: + case NDS32::fixup_NDS32_9_PCREL_RELA: + if (!isInt<9>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC9 fixup"); + return 0; + } + Value >>= 1; + break; + case NDS32::fixup_NDS32_15_PCREL_RELA: + if (!isInt<15>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC15 fixup"); + return 0; + } + Value >>= 1; + break; + case NDS32::fixup_NDS32_17_PCREL_RELA: + if (!isInt<17>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC17 fixup"); + return 0; + } + Value >>= 1; + break; + case NDS32::fixup_NDS32_25_PCREL_RELA: + if (!isInt<25>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC25 fixup"); + return 0; + } + Value >>= 1; + break; + } + return Value; } MCObjectWriter * Index: lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.cpp =================================================================== --- lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.cpp +++ lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.cpp @@ -232,6 +232,17 @@ getBranchTargetImm8sEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetImm8sEncoding expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_9_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); return 0; } @@ -240,6 +251,17 @@ getBranchTargetImm8s32BitEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetImm8sEncoding expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_9_32BIT_INSN_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); return 0; } @@ -248,6 +270,14 @@ getBranchTargetEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + if (MO.isImm()) return MO.getImm(); + + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_15_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); + return 0; } @@ -256,6 +286,14 @@ getBranchZeroTargetEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + if (MO.isImm()) return MO.getImm(); + + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_17_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); + return 0; } @@ -265,6 +303,15 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, we have nothing to do. + if (MO.isImm()) return MO.getImm(); + assert(MO.isExpr() && "Unexpected branch target type!"); + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_25_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); + return 0; } Index: lib/Target/NDS32/NDS32Predicate.td =================================================================== --- lib/Target/NDS32/NDS32Predicate.td +++ lib/Target/NDS32/NDS32Predicate.td @@ -252,31 +252,57 @@ // Branch/Jump target Operands Predicates // +def NDS32JumpTarget : AsmOperandClass { + let Name = "NDS32JumpTarget"; + let ParserMethod = "parseJumpTarget"; + let PredicateMethod = "isImm"; + let RenderMethod = "addImmOperands"; +} + def nds32_jump_target : Operand { + let ParserMatchClass = NDS32JumpTarget; let OperandType = "OPERAND_PCREL"; } def nds32_jal_target : Operand { + let ParserMatchClass = NDS32JumpTarget; + let EncoderMethod = "getJumpTargetOpValue"; + let DecoderMethod = "DecodeJumpTarget"; let OperandType = "OPERAND_PCREL"; } def nds32_j_target : Operand { + let ParserMatchClass = NDS32JumpTarget; + let EncoderMethod = "getJumpTargetOpValue"; + let DecoderMethod = "DecodeJumpTarget"; let OperandType = "OPERAND_PCREL"; } def brtarget : Operand { + let ParserMatchClass = NDS32JumpTarget; + let EncoderMethod = "getBranchTargetEncoding"; + let DecoderMethod = "DecodeBranchTarget"; let OperandType = "OPERAND_PCREL"; } def brzerotarget : Operand { + let ParserMatchClass = NDS32JumpTarget; + let EncoderMethod = "getBranchZeroTargetEncoding"; + let DecoderMethod = "DecodeBranchZeroTarget"; let OperandType = "OPERAND_PCREL"; } def brtargetImm8s : Operand { + let ParserMatchClass = NDS32JumpTarget; + let EncoderMethod = "getBranchTargetImm8sEncoding"; + let DecoderMethod = "DecodeBranchTargetImm8s"; let OperandType = "OPERAND_PCREL"; } def brtargetImm8s_32bit : Operand { + let ParserMatchClass = NDS32JumpTarget; + let EncoderMethod = "getBranchTargetImm8s32BitEncoding"; + let DecoderMethod = "DecodeBranchTargetImm8s"; let OperandType = "OPERAND_PCREL"; } Index: test/MC/NDS32/nds32-branches.s =================================================================== --- /dev/null +++ test/MC/NDS32/nds32-branches.s @@ -0,0 +1,33 @@ +! RUN: llvm-mc -triple nds32 -filetype=obj -o %t %s +! RUN: llvm-objdump -d -r -triple nds32 %t | FileCheck %s +foo: + j .LBB0_1 + jal .LBB0_1 + beq $r1, $r0, .LBB0_1 + bne $r1, $r0, .LBB0_1 + bnez $r2, .LBB0_1 + beqz $r2, .LBB0_1 + bgtz $r2, .LBB0_1 + bgez $r2, .LBB0_1 + bltz $r2, .LBB0_1 + blez $r2, .LBB0_1 + beqc $r1, 2, .LBB0_1 + bnec $r1, 2, .LBB0_1 + beqz38 $r2, .LBB0_1 + bnez38 $r2, .LBB0_1 +.LBB0_1: + +! CHECK: 48 00 00 1a j 52 +! CHECK: 49 00 00 18 jal 48 +! CHECK: 4c 10 00 16 beq $r1, $r0, 44 +! CHECK: 4c 10 40 14 bne $r1, $r0, 40 +! CHECK: 4e 23 00 12 bnez $r2, 36 +! CHECK: 4e 22 00 10 beqz $r2, 32 +! CHECK: 4e 26 00 0e bgtz $r2, 28 +! CHECK: 4e 24 00 0c bgez $r2, 24 +! CHECK: 4e 25 00 0a bltz $r2, 20 +! CHECK: 4e 27 00 08 blez $r2, 16 +! CHECK: 5a 10 02 06 beqc $r1, 2, 12 +! CHECK: 5a 18 02 04 bnec $r1, 2, 8 +! CHECK: c2 02 beqz38 $r2, 4 +! CHECK: ca 01 bnez38 $r2, 2 Index: test/MC/NDS32/reloc-call.s =================================================================== --- /dev/null +++ test/MC/NDS32/reloc-call.s @@ -0,0 +1,12 @@ +! RUN: llvm-mc -triple=nds32 -filetype=obj %s -o - | \ +! RUN: llvm-readobj -r | FileCheck -check-prefix=OBJ %s + .globl bar + .type bar,@function +bar: + jal foo +! OBJ: Relocations [ +! OBJ: Section {{.*}} .rela.text { +! OBJ-NEXT: 0x{{[0-9,A-F]+}} R_NDS32_25_PCREL_RELA foo 0x0 +! OBJ: } +! OBJ: ] +