From 582836faafcb458161947a72df27752fe5f76171 Mon Sep 17 00:00:00 2001 From: Zi Xuan Wu Date: Fri, 18 Mar 2022 15:40:14 +0800 Subject: [PATCH] [CSKY] Enhance asm parser and relocation fixup for some special symbol address instruction Add processing of parsing and emiting lrw/jsri/jmpi instruction, including related fixup and relocation. Add relax support about pseudo instructions such as jbr/jbsr. Add objdump format support like arm in llvm-objdump. --- .../Target/CSKY/AsmParser/CSKYAsmParser.cpp | 119 ++++++++++++ llvm/lib/Target/CSKY/CSKYInstrAlias.td | 38 ++++ llvm/lib/Target/CSKY/CSKYInstrInfo.td | 15 +- .../CSKY/MCTargetDesc/CSKYAsmBackend.cpp | 181 ++++++++++++++++-- .../Target/CSKY/MCTargetDesc/CSKYAsmBackend.h | 12 ++ .../CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp | 109 ++++++++++- .../CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp | 157 ++++++++++++++- .../CSKY/MCTargetDesc/CSKYMCCodeEmitter.h | 10 + .../CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp | 45 +++++ llvm/test/MC/CSKY/3e3r1.s | 22 +++ llvm/test/MC/CSKY/801.s | 19 ++ llvm/test/MC/CSKY/branch-relax-801.s | 44 +++++ llvm/test/MC/CSKY/branch-relax-803.s | 35 ++++ llvm/test/MC/CSKY/bsr.s | 54 ++++++ llvm/test/MC/CSKY/jmpi.s | 20 ++ llvm/test/MC/CSKY/jsri.s | 73 +++++++ llvm/test/MC/CSKY/lrs.s | 57 ++++++ llvm/test/MC/CSKY/lrw.s | 73 +++++++ llvm/test/MC/CSKY/tls_gd.s | 22 +++ llvm/test/MC/CSKY/tls_ie.s | 22 +++ llvm/test/MC/CSKY/tls_ld.s | 29 +++ llvm/test/MC/CSKY/tls_le.s | 14 ++ llvm/tools/llvm-objdump/llvm-objdump.cpp | 7 +- 23 files changed, 1146 insertions(+), 31 deletions(-) create mode 100644 llvm/lib/Target/CSKY/CSKYInstrAlias.td create mode 100644 llvm/test/MC/CSKY/3e3r1.s create mode 100644 llvm/test/MC/CSKY/801.s create mode 100644 llvm/test/MC/CSKY/branch-relax-801.s create mode 100644 llvm/test/MC/CSKY/branch-relax-803.s create mode 100644 llvm/test/MC/CSKY/bsr.s create mode 100644 llvm/test/MC/CSKY/jmpi.s create mode 100644 llvm/test/MC/CSKY/jsri.s create mode 100644 llvm/test/MC/CSKY/lrs.s create mode 100644 llvm/test/MC/CSKY/lrw.s create mode 100644 llvm/test/MC/CSKY/tls_gd.s create mode 100644 llvm/test/MC/CSKY/tls_ie.s create mode 100644 llvm/test/MC/CSKY/tls_ld.s create mode 100644 llvm/test/MC/CSKY/tls_le.s diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp index aca05ee8fcfa..f67147a60c61 100644 --- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp +++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp @@ -86,6 +86,9 @@ class CSKYAsmParser : public MCTargetAsmParser { bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, MCStreamer &Out); + bool processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); + bool processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); + bool processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); CSKYTargetStreamer &getTargetStreamer() { assert(getParser().getStreamer().getTargetStreamer() && @@ -128,7 +131,11 @@ public: MCAsmParserExtension::Initialize(Parser); + // Cache the MCRegisterInfo. + MRI = getContext().getRegisterInfo(); + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + getTargetStreamer().emitTargetAttributes(STI); } }; @@ -813,6 +820,96 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, llvm_unreachable("Unknown match type detected!"); } +bool CSKYAsmParser::processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) { + Inst.setLoc(IDLoc); + + unsigned Opcode; + MCOperand Op; + if (Inst.getOpcode() == CSKY::PseudoLRW16) + Opcode = CSKY::LRW16; + else + Opcode = CSKY::LRW32; + + if (Inst.getOperand(1).isImm()) { + if (isUInt<8>(Inst.getOperand(1).getImm()) && + Inst.getOperand(0).getReg() <= CSKY::R7) { + Opcode = CSKY::MOVI16; + } else if (getSTI().getFeatureBits()[CSKY::HasE2] && + isUInt<16>(Inst.getOperand(1).getImm())) { + Opcode = CSKY::MOVI32; + } else { + auto *Expr = getTargetStreamer().addConstantPoolEntry( + MCConstantExpr::create(Inst.getOperand(1).getImm(), getContext()), + Inst.getLoc()); + Inst.erase(std::prev(Inst.end())); + Inst.addOperand(MCOperand::createExpr(Expr)); + } + } else { + const MCExpr *AdjustExpr = nullptr; + if (const CSKYMCExpr *CSKYExpr = + dyn_cast(Inst.getOperand(1).getExpr())) { + if (CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSGD || + CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSIE || + CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSLDM) { + MCSymbol *Dot = getContext().createNamedTempSymbol(); + Out.emitLabel(Dot); + AdjustExpr = MCSymbolRefExpr::create(Dot, getContext()); + } + } + auto *Expr = getTargetStreamer().addConstantPoolEntry( + Inst.getOperand(1).getExpr(), Inst.getLoc(), AdjustExpr); + Inst.erase(std::prev(Inst.end())); + Inst.addOperand(MCOperand::createExpr(Expr)); + } + + Inst.setOpcode(Opcode); + + Out.emitInstruction(Inst, getSTI()); + return false; +} + +bool CSKYAsmParser::processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) { + Inst.setLoc(IDLoc); + + if (Inst.getOperand(0).isImm()) { + const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( + MCConstantExpr::create(Inst.getOperand(0).getImm(), getContext()), + Inst.getLoc()); + Inst.setOpcode(CSKY::JSRI32); + Inst.erase(std::prev(Inst.end())); + Inst.addOperand(MCOperand::createExpr(Expr)); + } else { + const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( + Inst.getOperand(0).getExpr(), Inst.getLoc()); + Inst.setOpcode(CSKY::JBSR32); + Inst.addOperand(MCOperand::createExpr(Expr)); + } + + Out.emitInstruction(Inst, getSTI()); + return false; +} + +bool CSKYAsmParser::processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) { + Inst.setLoc(IDLoc); + + if (Inst.getOperand(0).isImm()) { + const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( + MCConstantExpr::create(Inst.getOperand(0).getImm(), getContext()), + Inst.getLoc()); + Inst.setOpcode(CSKY::JMPI32); + Inst.erase(std::prev(Inst.end())); + Inst.addOperand(MCOperand::createExpr(Expr)); + } else { + const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( + Inst.getOperand(0).getExpr(), Inst.getLoc()); + Inst.setOpcode(CSKY::JBR32); + Inst.addOperand(MCOperand::createExpr(Expr)); + } + + Out.emitInstruction(Inst, getSTI()); + return false; +} + bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, MCStreamer &Out) { @@ -870,6 +967,28 @@ bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, Inst.erase(std::next(Inst.begin())); Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C)); break; + case CSKY::PseudoLRW16: + case CSKY::PseudoLRW32: + return processLRW(Inst, IDLoc, Out); + case CSKY::PseudoJSRI32: + return processJSRI(Inst, IDLoc, Out); + case CSKY::PseudoJMPI32: + return processJMPI(Inst, IDLoc, Out); + case CSKY::JBSR32: + case CSKY::JBR16: + case CSKY::JBT16: + case CSKY::JBF16: + case CSKY::JBR32: + case CSKY::JBT32: + case CSKY::JBF32: + unsigned Num = Inst.getNumOperands() - 1; + assert(Inst.getOperand(Num).isExpr()); + + const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( + Inst.getOperand(Num).getExpr(), Inst.getLoc()); + + Inst.addOperand(MCOperand::createExpr(Expr)); + break; } emitToStreamer(Out, Inst); diff --git a/llvm/lib/Target/CSKY/CSKYInstrAlias.td b/llvm/lib/Target/CSKY/CSKYInstrAlias.td new file mode 100644 index 000000000000..e3c0538e752e --- /dev/null +++ b/llvm/lib/Target/CSKY/CSKYInstrAlias.td @@ -0,0 +1,38 @@ +//===-- CSKYInstrAlias.td - Target Description for CSKY ----*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes the CSKY instructions alias. +// +//===----------------------------------------------------------------------===// + +def : InstAlias<"nop", (MOV16 R0, R0)>; +def : InstAlias<"nop", (MOV32 R0, R0)>, Requires<[iHasE2]>; + +def : InstAlias<"bgeni16 $dst, $imm", (BGENI GPR:$dst, uimm5:$imm)>; +def : InstAlias<"bgeni32 $dst, $imm", (BGENI GPR:$dst, uimm5:$imm)>; + +def : InstAlias<"bsr $dst", (BSR32 call_symbol:$dst)>; + +def : InstAlias<"grs\t$rz, $offset", (GRS32 GPR:$rz, bare_symbol:$offset)>; + +def : InstAlias<"jbsr\t$src1", (JBSR32 call_symbol:$src1)>; + +def : InstAlias<"jbr $dst", (JBR16 br_symbol_16bit:$dst)>; +def : InstAlias<"jbt $dst", (JBT16 C, br_symbol_16bit:$dst)>; +def : InstAlias<"jbf $dst", (JBF16 C, br_symbol_16bit:$dst)>; + +def : InstAlias<"lrw $rz, $src", (PseudoLRW16 mGPR:$rz, bare_symbol:$src)>; +def : InstAlias<"lrw $rz, $src", (LRW16 mGPR:$rz, constpool_symbol_16bit:$src)>; +def : InstAlias<"lrw $rz, $src", (PseudoLRW32 GPR:$rz, bare_symbol:$src)>; +def : InstAlias<"lrw $rz, $src", (LRW32 GPR:$rz, constpool_symbol:$src)>; + +def : InstAlias<"jsri $dst", (PseudoJSRI32 call_symbol:$dst)>; +def : InstAlias<"jsri $dst", (JSRI32 constpool_symbol:$dst)>; + +def : InstAlias<"jmpi $dst", (PseudoJMPI32 br_symbol:$dst)>; +def : InstAlias<"jmpi $dst", (JMPI32 constpool_symbol:$dst)>; \ No newline at end of file diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td index a782efe7f4f4..e3edf8280c75 100644 --- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td +++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td @@ -709,8 +709,6 @@ let Predicates= [iHasE2] in { def MOVI32 : I_16_MOV<0x10, "movi32", uimm16>; let Size = 4, isCodeGenOnly = 0 in def BGENI : CSKYPseudo<(outs GPR:$dst), (ins uimm5:$imm), "bgeni\t$dst, $imm", []>; - def : InstAlias<"bgeni16 $dst, $imm", (BGENI GPR:$dst, uimm5:$imm)>; - def : InstAlias<"bgeni32 $dst, $imm", (BGENI GPR:$dst, uimm5:$imm)>; def MOVIH32 : I_16_MOV<0x11, "movih32", uimm16_16_xform>; def MVC32 : R_Z_1<0x1, 0x8, "mvc32">; let isCodeGenOnly = 1 in @@ -779,8 +777,6 @@ def BNEZAD32 : CSKY32Inst; -def : InstAlias<"bsr $dst", (BSR32 call_symbol:$dst)>; - def BSR32_BR : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>{ let isCodeGenOnly = 1; let isBranch = 1; @@ -804,7 +800,6 @@ let Predicates = [iHas2E3] in { def GRS32 : I_18_Z_L<0x3, "grs32\t$rz, $offset", (outs GPR:$rz), (ins bare_symbol:$offset), []>; -def : InstAlias<"grs\t$rz, $offset", (GRS32 GPR:$rz, bare_symbol:$offset)>; let Uses = [R28] in { def LRS32B : I_18_Z_L<0x0, "lrs32.b\t$rz, $offset", @@ -1291,8 +1286,6 @@ let Predicates = [iHasE2] in { let isCall = 1, Defs = [ R15 ], mayLoad = 1, Size = 4, isCodeGenOnly = 0 in def JBSR32 : CSKYPseudo<(outs), (ins call_symbol:$src1), "jbsr32\t$src1", []>; -def : InstAlias<"jbsr\t$src1", (JBSR32 call_symbol:$src1)>; - def JBR32 : CSKYPseudo<(outs), (ins br_symbol:$src1), "jbr32\t$src1", []> { let isBranch = 1; let isTerminator = 1; @@ -1338,18 +1331,13 @@ let mayLoad = 1, Size = 2, isCodeGenOnly = 0 in def PseudoLRW32 : CSKYPseudo<(outs GPR:$rz), (ins bare_symbol:$src), "lrw32 $rz, $src", []>; -def : InstAlias<"lrw $rz, $src", (PseudoLRW32 GPR:$rz, bare_symbol:$src)>; -def : InstAlias<"lrw $rz, $src", (LRW32 GPR:$rz, constpool_symbol:$src)>; + let mayLoad = 1, Size = 4, isCodeGenOnly = 0 in def PseudoJSRI32 : CSKYPseudo<(outs), (ins call_symbol:$src), "jsri32 $src", []>; -def : InstAlias<"jsri $dst", (PseudoJSRI32 call_symbol:$dst)>; -def : InstAlias<"jsri $dst", (JSRI32 constpool_symbol:$dst)>; let mayLoad = 1, Size = 4, isCodeGenOnly = 0 in def PseudoJMPI32 : CSKYPseudo<(outs), (ins br_symbol:$src), "jmpi32 $src", []>; -def : InstAlias<"jmpi $dst", (PseudoJMPI32 br_symbol:$dst)>; -def : InstAlias<"jmpi $dst", (JMPI32 constpool_symbol:$dst)>; let isNotDuplicable = 1, mayLoad = 1, mayStore = 0, Size = 8 in def PseudoTLSLA32 : CSKYPseudo<(outs GPR:$dst1, GPR:$dst2), @@ -1362,3 +1350,4 @@ def CONSTPOOL_ENTRY : CSKYPseudo<(outs), include "CSKYInstrInfo16Instr.td" include "CSKYInstrInfoF1.td" include "CSKYInstrInfoF2.td" +include "CSKYInstrAlias.td" \ No newline at end of file diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp index daa655416c47..215b453739a3 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp @@ -88,6 +88,13 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, switch (Fixup.getTargetKind()) { default: llvm_unreachable("Unknown fixup kind!"); + case CSKY::fixup_csky_got32: + case CSKY::fixup_csky_got_imm18_scale4: + case CSKY::fixup_csky_gotoff: + case CSKY::fixup_csky_gotpc: + case CSKY::fixup_csky_plt32: + case CSKY::fixup_csky_plt_imm18_scale4: + llvm_unreachable("Relocation should be unconditionally forced\n"); case FK_Data_1: case FK_Data_2: case FK_Data_4: @@ -123,6 +130,71 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned."); return (Value >> 1) & 0x3ffff; + case CSKY::fixup_csky_pcrel_uimm8_scale4: { + if (!isUIntN(10, Value)) + Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); + if (Value & 0x3) + Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned."); + + unsigned IMM4L = (Value >> 2) & 0xf; + unsigned IMM4H = (Value >> 6) & 0xf; + + Value = (IMM4H << 21) | (IMM4L << 4); + return Value; + } + case CSKY::fixup_csky_pcrel_imm10_scale2: + if (!isIntN(11, Value)) + Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); + if (Value & 0x1) + Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned."); + + return (Value >> 1) & 0x3ff; + case CSKY::fixup_csky_pcrel_uimm7_scale4: + if (!isUIntN(9, Value)) + Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); + if (Value & 0x3) + Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned."); + + if ((Value & 0xff) <= 0b111111100) { + unsigned IMM5L = (Value >> 2) & 0x1f; + unsigned IMM2H = (Value >> 7) & 0x3; + + Value = (1 << 12) | (IMM2H << 8) | IMM5L; + } else { + unsigned IMM5L = (!Value >> 2) & 0x1f; + unsigned IMM2H = (!Value >> 7) & 0x3; + + Value = (IMM2H << 8) | IMM5L; + } + + return Value & 0xffff; + } +} + +bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, + bool Resolved, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout, + const bool WasForced) const { + // Return true if the symbol is actually unresolved. + // Resolved could be always false when shouldForceRelocation return true. + // We use !WasForced to indicate that the symbol is unresolved and not forced + // by shouldForceRelocation. + if (!Resolved && !WasForced) + return true; + + int64_t Offset = int64_t(Value); + switch (Fixup.getTargetKind()) { + default: + return false; + case CSKY::fixup_csky_pcrel_imm10_scale2: + return !isShiftedInt<10, 1>(Offset); + case CSKY::fixup_csky_pcrel_imm16_scale2: + return !isShiftedInt<16, 1>(Offset); + case CSKY::fixup_csky_pcrel_imm26_scale2: + return !isShiftedInt<26, 1>(Offset); + case CSKY::fixup_csky_pcrel_uimm7_scale4: + return !isShiftedUInt<8, 2>(Offset); } } @@ -166,6 +238,50 @@ void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, } } +bool CSKYAsmBackend::mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const { + switch (Inst.getOpcode()) { + default: + return false; + case CSKY::JBR32: + case CSKY::JBT32: + case CSKY::JBF32: + case CSKY::JBSR32: + if (!STI.getFeatureBits()[CSKY::Has2E3]) + return false; + return true; + case CSKY::JBR16: + case CSKY::JBT16: + case CSKY::JBF16: + case CSKY::LRW16: + case CSKY::BR16: + return true; + } +} + +bool CSKYAsmBackend::shouldForceRelocation(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target) { + if (Fixup.getKind() >= FirstLiteralRelocationKind) + return true; + switch (Fixup.getTargetKind()) { + default: + break; + case CSKY::fixup_csky_got32: + case CSKY::fixup_csky_got_imm18_scale4: + case CSKY::fixup_csky_gotoff: + case CSKY::fixup_csky_gotpc: + case CSKY::fixup_csky_plt32: + case CSKY::fixup_csky_plt_imm18_scale4: + case CSKY::fixup_csky_doffset_imm18: + case CSKY::fixup_csky_doffset_imm18_scale2: + case CSKY::fixup_csky_doffset_imm18_scale4: + return true; + } + + return false; +} + bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const { @@ -174,23 +290,62 @@ bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, void CSKYAsmBackend::relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const { - llvm_unreachable("CSKYAsmBackend::relaxInstruction() unimplemented"); -} + MCInst Res; -bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, - const MCSubtargetInfo *STI) const { - if (Count % 2) - return false; + switch (Inst.getOpcode()) { + default: + Inst.dump(); + llvm_unreachable("Opcode not expected!"); + case CSKY::LRW16: + Res.setOpcode(CSKY::LRW32); + Res.addOperand(Inst.getOperand(0)); + Res.addOperand(Inst.getOperand(1)); + break; + case CSKY::BR16: + Res.setOpcode(CSKY::BR32); + Res.addOperand(Inst.getOperand(0)); + break; + case CSKY::JBSR32: + Res.setOpcode(CSKY::JSRI32); + Res.addOperand(Inst.getOperand(1)); + break; + case CSKY::JBR32: + Res.setOpcode(CSKY::JMPI32); + Res.addOperand(Inst.getOperand(1)); + break; + case CSKY::JBT32: + case CSKY::JBF32: + Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E); + Res.addOperand(Inst.getOperand(0)); + Res.addOperand(Inst.getOperand(1)); + Res.addOperand(Inst.getOperand(2)); + break; + case CSKY::JBR16: + Res.setOpcode(CSKY::JBR32); + Res.addOperand(Inst.getOperand(0)); + Res.addOperand(Inst.getOperand(1)); + break; + case CSKY::JBT16: + case CSKY::JBF16: + // ck801 + unsigned opcode; + if (STI.getFeatureBits()[CSKY::HasE2]) + opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32; + else + opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E; - // MOV32 r0, r0 - while (Count >= 4) { - OS.write("\xc4\x00\x48\x20", 4); - Count -= 4; + Res.setOpcode(opcode); + Res.addOperand(Inst.getOperand(0)); + Res.addOperand(Inst.getOperand(1)); + Res.addOperand(Inst.getOperand(2)); + break; } - // MOV16 r0, r0 - if (Count) - OS.write("\x6c\x03", 2); + Inst = std::move(Res); +} +bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { + OS.write_zeros(Count); return true; } diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h index 87503439fe1a..09b3ce6cc82b 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h @@ -40,9 +40,21 @@ public: void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override; + + bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved, + uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout, + const bool WasForced) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const override; + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target) override; + std::unique_ptr createObjectTargetWriter() const override; }; diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp index 163632632290..321a4145b207 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// +#include "CSKYFixupKinds.h" #include "CSKYMCTargetDesc.h" +#include "CSKYMCExpr.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCObjectWriter.h" @@ -33,10 +35,111 @@ unsigned CSKYELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { - // Determine the type of the relocation. - switch ((unsigned)Fixup.getKind()) { + const MCExpr *Expr = Fixup.getValue(); + // Determine the type of the relocation + unsigned Kind = Fixup.getTargetKind(); + MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); + + if (IsPCRel) { + switch (Kind) { + default: + LLVM_DEBUG(dbgs() << "Unknown Kind1 = " << Kind); + Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type"); + return ELF::R_CKCORE_NONE; + case FK_Data_4: + case FK_PCRel_4: + return ELF::R_CKCORE_PCREL32; + case CSKY::fixup_csky_pcrel_uimm16_scale4: + return ELF::R_CKCORE_PCREL_IMM16_4; + case CSKY::fixup_csky_pcrel_uimm8_scale4: + return ELF::R_CKCORE_PCREL_IMM8_4; + case CSKY::fixup_csky_pcrel_imm26_scale2: + return ELF::R_CKCORE_PCREL_IMM26_2; + case CSKY::fixup_csky_pcrel_imm18_scale2: + return ELF::R_CKCORE_PCREL_IMM18_2; + case CSKY::fixup_csky_pcrel_imm16_scale2: + return ELF::R_CKCORE_PCREL_IMM16_2; + case CSKY::fixup_csky_pcrel_imm10_scale2: + return ELF::R_CKCORE_PCREL_IMM10_2; + case CSKY::fixup_csky_pcrel_uimm7_scale4: + return ELF::R_CKCORE_PCREL_IMM7_4; + } + } + + switch (Kind) { default: - llvm_unreachable("invalid fixup kind!"); + LLVM_DEBUG(dbgs() << "Unknown Kind2 = " << Kind); + Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type"); + return ELF::R_CKCORE_NONE; + case FK_Data_1: + Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported"); + return ELF::R_CKCORE_NONE; + case FK_Data_2: + Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported"); + return ELF::R_CKCORE_NONE; + case FK_Data_4: + if (Expr->getKind() == MCExpr::Target) { + auto TK = cast(Expr)->getKind(); + if (TK == CSKYMCExpr::VK_CSKY_ADDR) + return ELF::R_CKCORE_ADDR32; + if (TK == CSKYMCExpr::VK_CSKY_GOT) + return ELF::R_CKCORE_GOT32; + if (TK == CSKYMCExpr::VK_CSKY_GOTOFF) + return ELF::R_CKCORE_GOTOFF; + if (TK == CSKYMCExpr::VK_CSKY_PLT) + return ELF::R_CKCORE_PLT32; + if (TK == CSKYMCExpr::VK_CSKY_TLSIE) + return ELF::R_CKCORE_TLS_IE32; + if (TK == CSKYMCExpr::VK_CSKY_TLSLE) + return ELF::R_CKCORE_TLS_LE32; + if (TK == CSKYMCExpr::VK_CSKY_TLSGD) + return ELF::R_CKCORE_TLS_GD32; + if (TK == CSKYMCExpr::VK_CSKY_TLSLDM) + return ELF::R_CKCORE_TLS_LDM32; + if (TK == CSKYMCExpr::VK_CSKY_TLSLDO) + return ELF::R_CKCORE_TLS_LDO32; + if (TK == CSKYMCExpr::VK_CSKY_GOTPC) + return ELF::R_CKCORE_GOTPC; + if (TK == CSKYMCExpr::VK_CSKY_None) + return ELF::R_CKCORE_ADDR32; + + LLVM_DEBUG(dbgs() << "Unknown FK_Data_4 TK = " << TK); + Ctx.reportError(Fixup.getLoc(), "unknown target FK_Data_4"); + } else { + switch (Modifier) { + default: + Ctx.reportError(Fixup.getLoc(), + "invalid fixup for 4-byte data relocation"); + return ELF::R_CKCORE_NONE; + case MCSymbolRefExpr::VK_GOT: + return ELF::R_CKCORE_GOT32; + case MCSymbolRefExpr::VK_GOTOFF: + return ELF::R_CKCORE_GOTOFF; + case MCSymbolRefExpr::VK_PLT: + return ELF::R_CKCORE_PLT32; + case MCSymbolRefExpr::VK_None: + return ELF::R_CKCORE_ADDR32; + } + } + case FK_Data_8: + Ctx.reportError(Fixup.getLoc(), "8-byte data relocations not supported"); + return ELF::R_CKCORE_NONE; + case CSKY::fixup_csky_addr32: + return ELF::R_CKCORE_ADDR32; + case CSKY::fixup_csky_addr_hi16: + return ELF::R_CKCORE_ADDR_HI16; + case CSKY::fixup_csky_addr_lo16: + return ELF::R_CKCORE_ADDR_LO16; + case CSKY::fixup_csky_doffset_imm18: + return ELF::R_CKCORE_DOFFSET_IMM18; + case CSKY::fixup_csky_doffset_imm18_scale2: + return ELF::R_CKCORE_DOFFSET_IMM18_2; + case CSKY::fixup_csky_doffset_imm18_scale4: + return ELF::R_CKCORE_DOFFSET_IMM18_4; + case CSKY::fixup_csky_got_imm18_scale4: + return ELF::R_CKCORE_GOT_IMM18_4; + case CSKY::fixup_csky_plt_imm18_scale4: + return ELF::R_CKCORE_PLT_IMM18_4; } } diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp index 29b91173bc11..540f901fd479 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp @@ -67,15 +67,170 @@ static void writeData(uint32_t Bin, unsigned Size, raw_ostream &OS) { support::endian::write(OS, LO16, support::little); } +void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + MCInst TmpInst; + + uint32_t Binary; + + TmpInst = + MCInstBuilder(MI.getOpcode() == CSKY::JBT_E ? CSKY::BF16 : CSKY::BT16) + .addOperand(MI.getOperand(0)) + .addImm(6); + Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); + writeData(Binary, 2, OS); + + if (!STI.getFeatureBits()[CSKY::Has2E3]) + TmpInst = MCInstBuilder(CSKY::BR32) + .addOperand(MI.getOperand(1)) + .addOperand(MI.getOperand(2)); + else + TmpInst = MCInstBuilder(CSKY::JMPI32).addOperand(MI.getOperand(2)); + Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); + Fixups[Fixups.size() - 1].setOffset(2); + writeData(Binary, 4, OS); +} + +void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + MCInst TmpInst; + uint32_t Binary; + unsigned Size = MI.getOpcode() == CSKY::NEG32 ? 4 : 2; + + TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)); + Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); + writeData(Binary, Size, OS); + + TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(0)) + .addImm(1); + Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); + writeData(Binary, Size, OS); +} + +void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + MCInst TmpInst; + uint32_t Binary; + unsigned Size = MI.getOpcode() == CSKY::RSUBI32 ? 4 : 2; + + TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)); + Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); + writeData(Binary, Size, OS); + + TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(0)) + .addImm(MI.getOperand(2).getImm() + 1); + Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); + writeData(Binary, Size, OS); +} + void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCInstrDesc &Desc = MII.get(MI.getOpcode()); unsigned Size = Desc.getSize(); + MCInst TmpInst; + + switch (MI.getOpcode()) { + default: + TmpInst = MI; + break; + case CSKY::JBT_E: + case CSKY::JBF_E: + expandJBTF(MI, OS, Fixups, STI); + MCNumEmitted += 2; + return; + case CSKY::NEG32: + case CSKY::NEG16: + expandNEG(MI, OS, Fixups, STI); + MCNumEmitted += 2; + return; + case CSKY::RSUBI32: + case CSKY::RSUBI16: + expandRSUBI(MI, OS, Fixups, STI); + MCNumEmitted += 2; + return; + case CSKY::JBSR32: + TmpInst = MCInstBuilder(CSKY::BSR32).addOperand(MI.getOperand(0)); + break; + case CSKY::JBR16: + TmpInst = MCInstBuilder(CSKY::BR16).addOperand(MI.getOperand(0)); + break; + case CSKY::JBR32: + TmpInst = MCInstBuilder(CSKY::BR32).addOperand(MI.getOperand(0)); + break; + case CSKY::JBT16: + TmpInst = MCInstBuilder(CSKY::BT16) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)); + break; + case CSKY::JBT32: + TmpInst = MCInstBuilder(CSKY::BT32) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)); + break; + case CSKY::JBF16: + TmpInst = MCInstBuilder(CSKY::BF16) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)); + break; + case CSKY::JBF32: + TmpInst = MCInstBuilder(CSKY::BF32) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)); + break; + case CSKY::LRW32_Gen: + TmpInst = MCInstBuilder(CSKY::LRW32) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(2)); + break; + case CSKY::LRW16_Gen: + TmpInst = MCInstBuilder(CSKY::LRW16) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(2)); + break; + case CSKY::CMPLEI32: + TmpInst = MCInstBuilder(CSKY::CMPLTI32) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)) + .addImm(MI.getOperand(2).getImm() + 1); + break; + case CSKY::CMPLEI16: + TmpInst = MCInstBuilder(CSKY::CMPLTI16) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)) + .addImm(MI.getOperand(2).getImm() + 1); + break; + case CSKY::ROTRI32: + TmpInst = MCInstBuilder(CSKY::ROTLI32) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)) + .addImm(32 - MI.getOperand(2).getImm()); + break; + case CSKY::BGENI: + auto V = 1 << MI.getOperand(1).getImm(); + TmpInst = + MCInstBuilder(CSKY::MOVI32).addOperand(MI.getOperand(0)).addImm(V); + break; + } + ++MCNumEmitted; - uint32_t Bin = getBinaryCodeForInstr(MI, Fixups, STI); + uint32_t Bin = getBinaryCodeForInstr(TmpInst, Fixups, STI); uint16_t LO16 = static_cast(Bin); uint16_t HI16 = static_cast(Bin >> 16); diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h index 0720d3392020..128430197cc5 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h @@ -171,6 +171,16 @@ public: Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); return 0; } + + void expandJBTF(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + void expandNEG(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + void expandRSUBI(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; }; } // namespace llvm diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp index c41a20060e48..1a69dc8acde0 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp @@ -19,6 +19,7 @@ #include "CSKYTargetStreamer.h" #include "TargetInfo/CSKYTargetInfo.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -107,6 +108,49 @@ static MCTargetStreamer *createCSKYNullTargetStreamer(MCStreamer &S) { return new CSKYTargetStreamer(S); } +namespace { + +class CSKYMCInstrAnalysis : public MCInstrAnalysis { +public: + explicit CSKYMCInstrAnalysis(const MCInstrInfo *Info) + : MCInstrAnalysis(Info) {} + + bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const override { + if (isConditionalBranch(Inst) || isUnconditionalBranch(Inst)) { + int64_t Imm; + Imm = Inst.getOperand(Inst.getNumOperands() - 1).getImm(); + Target = Addr + Imm; + return true; + } + + if (Inst.getOpcode() == CSKY::BSR32) { + Target = Addr + Inst.getOperand(0).getImm(); + return true; + } + + switch (Inst.getOpcode()) { + default: + return false; + case CSKY::LRW16: + case CSKY::LRW32: + case CSKY::JSRI32: + case CSKY::JMPI32: + int64_t Imm = Inst.getOperand(Inst.getNumOperands() - 1).getImm(); + Target = ((Addr + Imm) & 0xFFFFFFFC); + return true; + } + + return false; + } +}; + +} // end anonymous namespace + +static MCInstrAnalysis *createCSKYInstrAnalysis(const MCInstrInfo *Info) { + return new CSKYMCInstrAnalysis(Info); +} + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYTargetMC() { auto &CSKYTarget = getTheCSKYTarget(); TargetRegistry::RegisterMCAsmBackend(CSKYTarget, createCSKYAsmBackend); @@ -125,4 +169,5 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYTargetMC() { // Register the null target streamer. TargetRegistry::RegisterNullTargetStreamer(CSKYTarget, createCSKYNullTargetStreamer); + TargetRegistry::RegisterMCInstrAnalysis(CSKYTarget, createCSKYInstrAnalysis); } diff --git a/llvm/test/MC/CSKY/3e3r1.s b/llvm/test/MC/CSKY/3e3r1.s new file mode 100644 index 000000000000..2aebc90083c0 --- /dev/null +++ b/llvm/test/MC/CSKY/3e3r1.s @@ -0,0 +1,22 @@ +# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases -mattr=+3e3r1 \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+3e3r1 < %s \ +# RUN: | llvm-objdump --mattr=+3e3r1 -M no-aliases -M abi-names -d -r - \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s + + +# CHECK-ASM-AND-OBJ: mul.s32 a3, l0, a1 +# CHECK-ASM: encoding: [0x24,0xf8,0x03,0x82] +mul.s32 a3, l0, a1 + +# CHECK-ASM-AND-OBJ: mul.u32 a3, l0, a1 +# CHECK-ASM: encoding: [0x24,0xf8,0x03,0x80] +mul.u32 a3, l0, a1 + +# CHECK-ASM-AND-OBJ: mula.s32 a3, l0, a1 +# CHECK-ASM: encoding: [0x24,0xf8,0x83,0x82] +mula.s32 a3, l0, a1 + +# CHECK-ASM-AND-OBJ: mula.u32 a3, l0, a1 +# CHECK-ASM: encoding: [0x24,0xf8,0x83,0x80] +mula.u32 a3, l0, a1 \ No newline at end of file diff --git a/llvm/test/MC/CSKY/801.s b/llvm/test/MC/CSKY/801.s new file mode 100644 index 000000000000..9b3d5ce394fc --- /dev/null +++ b/llvm/test/MC/CSKY/801.s @@ -0,0 +1,19 @@ +# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases -mattr=+e1 \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+e1 < %s \ +# RUN: | llvm-objdump --mattr=+e1 -M no-aliases -d -r - \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: ipush +# CHECK-ASM: encoding: [0x62,0x14] +ipush16 + +# CHECK-ASM-AND-OBJ: ipop +# CHECK-ASM: encoding: [0x63,0x14] +ipop16 + +# RUN: not llvm-mc -triple csky -mattr=+e1 --defsym=ERR=1 < %s 2>&1 | FileCheck %s + +.ifdef ERR +ipush16 1 # CHECK: :[[#@LINE]]:9: error: invalid operand for instruction +.endif diff --git a/llvm/test/MC/CSKY/branch-relax-801.s b/llvm/test/MC/CSKY/branch-relax-801.s new file mode 100644 index 000000000000..87a51cd94740 --- /dev/null +++ b/llvm/test/MC/CSKY/branch-relax-801.s @@ -0,0 +1,44 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mcpu=ck801 < %s \ +# RUN: | llvm-objdump --mattr=+e1 --no-show-raw-insn -M no-aliases -d -r - \ +# RUN: | FileCheck -check-prefixes=CHECK-OBJ-CK801 %s +# RUN: llvm-mc -filetype=obj -triple=csky -mcpu=ck802 < %s \ +# RUN: | llvm-objdump --mattr=+e2 --no-show-raw-insn -M no-aliases -d -r - \ +# RUN: | FileCheck -check-prefixes=CHECK-OBJ-CK802 %s + +# CHECK-OBJ-CK801: 0: addu16 r1, r2, r3 +# CHECK-OBJ-CK801-NEXT: 2: bt16 0x8 +# CHECK-OBJ-CK801-NEXT: 4: br32 0x4bc +# CHECK-OBJ-CK801-NEXT: 8: addu16 r3, r2, r1 +# CHECK-OBJ-CK801: 4ba: addu16 r1, r2, r3 +# CHECK-OBJ-CK801-NEXT: 4bc: bf16 0x4c2 +# CHECK-OBJ-CK801-NEXT: 4be: br32 0x2 +# CHECK-OBJ-CK801-NEXT: 4c2: br32 0x2 +# CHECK-OBJ-CK801-NEXT: 4c6: addu16 r3, r2, r1 +# CHECK-OBJ-CK801-NEXT: 4c8: br16 0x4ca + +# CHECK-OBJ-CK802: 0: addu16 r1, r2, r3 +# CHECK-OBJ-CK802-NEXT: 2: bf32 0x96a +# CHECK-OBJ-CK802-NEXT: 6: addu16 r3, r2, r1 +# CHECK-OBJ-CK802: 968: addu16 r1, r2, r3 +# CHECK-OBJ-CK802-NEXT: 96a: bt32 0x2 +# CHECK-OBJ-CK802-NEXT: 96e: br32 0x2 +# CHECK-OBJ-CK802-NEXT: 972: addu16 r3, r2, r1 +# CHECK-OBJ-CK802-NEXT: 974: br16 0x976 + + addu16 r1, r2, r3 +.L1: + jbf .L2 + addu16 r3, r2, r1 + + .rept 600 + nop + .endr + + + addu16 r1, r2, r3 +.L2: + jbt .L1 + jbr .L1 + addu16 r3, r2, r1 + jbr .L3 +.L3: diff --git a/llvm/test/MC/CSKY/branch-relax-803.s b/llvm/test/MC/CSKY/branch-relax-803.s new file mode 100644 index 000000000000..6aacbe20ad14 --- /dev/null +++ b/llvm/test/MC/CSKY/branch-relax-803.s @@ -0,0 +1,35 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mcpu=ck803 < %s \ +# RUN: | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - \ +# RUN: | FileCheck -check-prefixes=CHECK-OBJ-CK803 %s + +# CHECK-OBJ-CK803: 0: addu16 r1, r2, r3 +# CHECK-OBJ-CK803-NEXT: 2: bt16 0x8 +# CHECK-OBJ-CK803-NEXT: 4: jmpi32 0x3a9a0 <$d.0> +# CHECK-OBJ-CK803-NEXT: 8: bsr32 0x3a990 <.text+0x3a990> +# CHECK-OBJ-CK803-NEXT: c: addu16 r3, r2, r1 +# CHECK-OBJ-CK803: 3a98e: addu16 r1, r2, r3 +# CHECK-OBJ-CK803-NEXT: 3a990: bf16 0x3a996 <.text+0x3a996> +# CHECK-OBJ-CK803-NEXT: 3a992: jmpi32 0x3a9a4 <$d.0+0x4> +# CHECK-OBJ-CK803-NEXT: 3a996: jmpi32 0x3a9a4 <$d.0+0x4> +# CHECK-OBJ-CK803-NEXT: 3a99a: addu16 r3, r2, r1 +# CHECK-OBJ-CK803-NEXT: 3a99c: br16 0x3a99e <.text+0x3a99e> + + + addu16 r1, r2, r3 +.L1: + jbf .L2 + jbsr .L2 + addu16 r3, r2, r1 + + .rept 60000 + nop + .endr + + + addu16 r1, r2, r3 +.L2: + jbt .L1 + jbr .L1 + addu16 r3, r2, r1 + jbr .L3 +.L3: diff --git a/llvm/test/MC/CSKY/bsr.s b/llvm/test/MC/CSKY/bsr.s new file mode 100644 index 000000000000..f4c79ec6d316 --- /dev/null +++ b/llvm/test/MC/CSKY/bsr.s @@ -0,0 +1,54 @@ +# RUN: llvm-mc -filetype=obj -triple=csky < %s \ +# RUN: | llvm-objdump --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + +.data +sec: + .long 0x77 +.text +tstart: + bsr lnk + bsr lnk - 4 + bsr lnk + 4 + .short 0x1C00 + bsr sec + bsr sec - 4 + bsr sec + 4 + +.L1: + bsr .L1 +.L2: + bsr .L2 - 1024 +.L3: + bsr .L3 + 1022 + +.L4: + bsr .L4 - 1026 +.L5: + bsr .L5 + 1024 + +.L6: + bsr .L6 - 64*1024*1024 +.L7: + bsr .L7 + 64*1024*1024 - 2 + + +# CHECK: 0: bsr32 0x0 +# CHECK: 00000000: R_CKCORE_PCREL_IMM26_2 lnk +# CHECK: 4: bsr32 0x4 +# CHECK: 00000004: R_CKCORE_PCREL_IMM26_2 lnk-0x4 +# CHECK: 8: bsr32 0x8 +# CHECK: 00000008: R_CKCORE_PCREL_IMM26_2 lnk+0x4 + +# CHECK: e: bsr32 0xe +# CHECK: 0000000e: R_CKCORE_PCREL_IMM26_2 .data +# CHECK: 12: bsr32 0x12 +# CHECK: 00000012: R_CKCORE_PCREL_IMM26_2 .data-0x4 +# CHECK: 16: bsr32 0x16 +# CHECK: 00000016: R_CKCORE_PCREL_IMM26_2 .data+0x4 +# CHECK: 1a: bsr32 0x1a +# CHECK: 1e: bsr32 0xfffffc1e +# CHECK: 22: bsr32 0x420 +# CHECK: 26: bsr32 0xfffffc24 +# CHECK: 2a: bsr32 0x42a +# CHECK: 2e: bsr32 0xfc00002e +# CHECK: 32: bsr32 0x4000030 \ No newline at end of file diff --git a/llvm/test/MC/CSKY/jmpi.s b/llvm/test/MC/CSKY/jmpi.s new file mode 100644 index 000000000000..a02aaac7b5c8 --- /dev/null +++ b/llvm/test/MC/CSKY/jmpi.s @@ -0,0 +1,20 @@ +# RUN: llvm-mc -filetype=obj -triple=csky < %s \ +# RUN: | llvm-objdump --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + + +.text + +LABEL: + bkpt + jmpi LABEL + bkpt + + +# CHECK: 0: bkpt +# CHECK-NEXT: 2: br32 0x0 +# CHECK-NEXT: 6: bkpt + + +# CHECK: 8: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000008: R_CKCORE_ADDR32 .text + diff --git a/llvm/test/MC/CSKY/jsri.s b/llvm/test/MC/CSKY/jsri.s new file mode 100644 index 000000000000..8342f89f61d9 --- /dev/null +++ b/llvm/test/MC/CSKY/jsri.s @@ -0,0 +1,73 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3 < %s \ +# RUN: | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + + +.data +sec: + .long 0x77 +.text +tstart: + jsri lnk + jsri lnk - 4 + jsri lnk + 4 + .short 0x1C00 + jsri sec + jsri sec - 4 + jsri sec + 4 + +.J1: + jsri .J1 +.J2: + jsri .J2 - 0x1000 +.J3: + jsri .J3 + 0x1000 + + jsri 0x01020304 + jsri 0xFFFFFFFE + + +# CHECK: 0: jsri32 0x30 <$d.4> +# CHECK-NEXT: 4: jsri32 0x34 <$d.4+0x4> +# CHECK-NEXT: 8: jsri32 0x38 <$d.4+0x8> + +# CHECK: c: 00 1c .short 0x1c00 + +# CHECK: e: jsri32 0x3c <$d.4+0xc> +# CHECK-NEXT: 12: jsri32 0x40 <$d.4+0x10> +# CHECK-NEXT: 16: jsri32 0x44 <$d.4+0x14> + + + +# CHECK: <.J1>: +# CHECK-NEXT: 1a: bsr32 0x1a + +# CHECK: <.J2>: +# CHECK-NEXT: 1e: bsr32 0xfffff01e <$d.4+0xffffffffffffefee> + +# CHECK: <.J3>: +# CHECK-NEXT: 22: bsr32 0x1022 <$d.4+0xff2> +# CHECK-NEXT: 26: jsri32 0x54 <$d.4+0x24> +# CHECK-NEXT: 2a: jsri32 0x58 <$d.4+0x28> +# CHECK-NEXT: 2e: bkpt + + +# CHECK: 30: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 00000030: R_CKCORE_ADDR32 lnk +# CHECK-NEXT: 34: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 00000034: R_CKCORE_ADDR32 lnk-0x4 +# CHECK-NEXT: 38: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 00000038: R_CKCORE_ADDR32 lnk+0x4 +# CHECK-NEXT: 3c: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 0000003c: R_CKCORE_ADDR32 .data +# CHECK-NEXT: 40: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 00000040: R_CKCORE_ADDR32 .data-0x4 +# CHECK-NEXT: 44: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 00000044: R_CKCORE_ADDR32 .data+0x4 +# CHECK-NEXT: 48: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 00000048: R_CKCORE_ADDR32 .text+0x1a +# CHECK-NEXT: 4c: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 0000004c: R_CKCORE_ADDR32 .text-0xfe2 +# CHECK-NEXT: 50: 00 00 00 00 .word 0x0 +# CHECK-NEXT: 00000050: R_CKCORE_ADDR32 .text+0x1022 +# CHECK-NEXT: 54: 04 03 02 01 .word 0x01020304 +# CHECK-NEXT: 58: fe ff ff ff .word 0xfffffffe diff --git a/llvm/test/MC/CSKY/lrs.s b/llvm/test/MC/CSKY/lrs.s new file mode 100644 index 000000000000..f0eb66bd388f --- /dev/null +++ b/llvm/test/MC/CSKY/lrs.s @@ -0,0 +1,57 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3 < %s \ +# RUN: | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + + +.data +sec: + .long 0x77 +.text +tstart: + lrs32.b r0,[lnk] + lrs32.b r0,[lnk - 4] + lrs32.b r0,[lnk + 4] + .short 0x1C00 + lrs32.h r0,[sec] + lrs32.h r0,[sec - 4] + lrs32.h r0,[sec + 4] + lrs32.b r0,[0] + lrs32.b r0,[0xFFFF] + lrs32.b r31,[0] +.L1: + lrs32.w r31,[.L1] +.L2: + lrs32.w r0, [.L2] +.L3: + lrs32.w r0, [.L3 - 64*1024] +.L4: + lrs32.w r0, [.L4 + 64*1024 - 2] + +# CHECK: 0: lrs32.b r0, [0] +# CHECK-NEXT: 00000000: R_CKCORE_DOFFSET_IMM18 lnk +# CHECK-NEXT: 4: lrs32.b r0, [0] +# CHECK-NEXT: 00000004: R_CKCORE_DOFFSET_IMM18 lnk-0x4 +# CHECK-NEXT: 8: lrs32.b r0, [0] +# CHECK-NEXT: 00000008: R_CKCORE_DOFFSET_IMM18 lnk+0x4 + +# CHECK: c: 00 1c .short 0x1c00 + +# CHECK: e: lrs32.h r0, [0] +# CHECK-NEXT: 0000000e: R_CKCORE_DOFFSET_IMM18_2 .data +# CHECK-NEXT: 12: lrs32.h r0, [0] +# CHECK-NEXT: 00000012: R_CKCORE_DOFFSET_IMM18_2 .data-0x4 +# CHECK-NEXT: 16: lrs32.h r0, [0] +# CHECK-NEXT: 00000016: R_CKCORE_DOFFSET_IMM18_2 .data+0x4 +# CHECK-NEXT: 1a: lrs32.b r0, [0] +# CHECK-NEXT: 0000001a: R_CKCORE_DOFFSET_IMM18 *ABS* +# CHECK-NEXT: 1e: lrs32.b r0, [0] +# CHECK-NEXT: 0000001e: R_CKCORE_DOFFSET_IMM18 *ABS*+0xffff +# CHECK-NEXT: 22: lrs32.b r31, [0] +# CHECK-NEXT: 00000022: R_CKCORE_DOFFSET_IMM18 *ABS* +# CHECK-NEXT: 26: lrs32.w r31, [0] +# CHECK-NEXT: 00000026: R_CKCORE_DOFFSET_IMM18_4 .text+0x26 +# CHECK-NEXT: 2a: lrs32.w r0, [0] +# CHECK-NEXT: 0000002a: R_CKCORE_DOFFSET_IMM18_4 .text+0x2a +# CHECK-NEXT: 2e: lrs32.w r0, [0] +# CHECK-NEXT: 0000002e: R_CKCORE_DOFFSET_IMM18_4 .text-0xffd2 +# CHECK-NEXT: 32: lrs32.w r0, [0] +# CHECK-NEXT: 00000032: R_CKCORE_DOFFSET_IMM18_4 .text+0x10030 diff --git a/llvm/test/MC/CSKY/lrw.s b/llvm/test/MC/CSKY/lrw.s new file mode 100644 index 000000000000..69eea7e128c3 --- /dev/null +++ b/llvm/test/MC/CSKY/lrw.s @@ -0,0 +1,73 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+e2 < %s \ +# RUN: | llvm-objdump --mattr=+e2 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + + +.data +sec: + .long 0x77 +.text +tstart: + lrw r0,lnk + lrw r0,lnk - 4 + lrw r0,lnk + 4 + .short 0x1C00 + lrw r0,sec + lrw r0,sec - 4 + lrw r0,sec + 4 + lrw r0,0 + lrw r0,0xFFFF + lrw r31,0 +.L1: + lrw r31,.L1 +.L2: + lrw r0, .L2 +.L3: + lrw r0, .L3 - 64*1024 +.L4: + lrw r0, .L4 + 64*1024 - 2 + + lrw r0,0x01020304 + lrw r0,0xFFFFFFFE + +# CHECK: 0: lrw16 r0, 0x28 <$d.4> +# CHECK-NEXT: 2: lrw16 r0, 0x2c <$d.4+0x4> +# CHECK-NEXT: 4: lrw16 r0, 0x30 <$d.4+0x8> + +# CHECK: 6: 00 1c .short 0x1c00 + +# CHECK: 8: lrw16 r0, 0x34 <$d.4+0xc> +# CHECK-NEXT: a: lrw16 r0, 0x38 <$d.4+0x10> +# CHECK-NEXT: c: lrw16 r0, 0x3c <$d.4+0x14> +# CHECK-NEXT: e: movi16 r0, 0 +# CHECK-NEXT: 10: movi32 r0, 65535 +# CHECK-NEXT: 14: movi32 r31, 0 +# CHECK-NEXT: 18: lrw32 r31, 0x40 <$d.4+0x18> +# CHECK-NEXT: 1c: lrw16 r0, 0x44 <$d.4+0x1c> +# CHECK-NEXT: 1e: lrw16 r0, 0x48 <$d.4+0x20> +# CHECK-NEXT: 20: lrw16 r0, 0x4c <$d.4+0x24> +# CHECK-NEXT: 22: lrw16 r0, 0x50 <$d.4+0x28> +# CHECK-NEXT: 24: lrw16 r0, 0x54 <$d.4+0x2c> + +# CHECK: 28: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000028: R_CKCORE_ADDR32 lnk +# CHECK-NEXT: 2c: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 0000002c: R_CKCORE_ADDR32 lnk-0x4 +# CHECK-NEXT: 30: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000030: R_CKCORE_ADDR32 lnk+0x4 +# CHECK-NEXT: 34: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000034: R_CKCORE_ADDR32 .data +# CHECK-NEXT: 38: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000038: R_CKCORE_ADDR32 .data-0x4 +# CHECK-NEXT: 3c: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 0000003c: R_CKCORE_ADDR32 .data+0x4 +# CHECK-NEXT: 40: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000040: R_CKCORE_ADDR32 .text+0x18 +# CHECK-NEXT: 44: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000044: R_CKCORE_ADDR32 .text+0x1c +# CHECK-NEXT: 48: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000048: R_CKCORE_ADDR32 .text-0xffe2 +# CHECK-NEXT: 4c: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 0000004c: R_CKCORE_ADDR32 .text+0x1001e +# CHECK-NEXT: 50: 04 03 02 01 .word 0x01020304 +# CHECK-NEXT: 54: fe ff ff ff .word 0xfffffffe + diff --git a/llvm/test/MC/CSKY/tls_gd.s b/llvm/test/MC/CSKY/tls_gd.s new file mode 100644 index 000000000000..3e1cc0623839 --- /dev/null +++ b/llvm/test/MC/CSKY/tls_gd.s @@ -0,0 +1,22 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3 < %s \ +# RUN: | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + +.LTLS0: + lrw16 r0, xxx@TLSGD32 + grs32 r2, .LTLS0 + addu16 r0, r0, r2 + lrw16 r3, __tls_get_addr@PLT + ldr32.w r3, (rgb, r3 << 0) + jsr16 r3 + +# CHECK: 0: lrw16 r0, 0x10 <$d.0> +# CHECK-NEXT: 2: grs32 r2, 0x0 +# CHECK-NEXT: 6: addu16 r0, r0, r2 +# CHECK-NEXT: 8: lrw16 r3, 0x14 <$d.0+0x4> +# CHECK-NEXT: a: ldr32.w r3, (r28, r3 << 0) +# CHECK-NEXT: e: jsr16 r3 + +# CHECK: 10: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000010: R_CKCORE_TLS_GD32 xxx+0x10 +# CHECK-NEXT: 14: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000014: R_CKCORE_PLT32 __tls_get_addr diff --git a/llvm/test/MC/CSKY/tls_ie.s b/llvm/test/MC/CSKY/tls_ie.s new file mode 100644 index 000000000000..1752dfc9b7f9 --- /dev/null +++ b/llvm/test/MC/CSKY/tls_ie.s @@ -0,0 +1,22 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3 < %s \ +# RUN: | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + +.LTLS0: + lrw16 r3, xxx@GOTTPOFF + grs32 r2, .LTLS0 + addu16 r3, r3, r2 + ld16.w r3, (r3, 0) + lsli32 r2, r31, 0 + str32.w r0, (r2, r3 << 0) + + +# CHECK: 0: lrw16 r3, 0x14 <$d.0> +# CHECK-NEXT: 2: grs32 r2, 0x0 +# CHECK-NEXT: 6: addu16 r3, r3, r2 +# CHECK-NEXT: 8: ld16.w r3, (r3, 0x0) +# CHECK-NEXT: a: lsli32 r2, r31, 0 +# CHECK-NEXT: e: str32.w r0, (r2, r3 << 0) +# CHECK-NEXT: 12: bkpt + +# CHECK: 14: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000014: R_CKCORE_TLS_IE32 xxx+0x14 diff --git a/llvm/test/MC/CSKY/tls_ld.s b/llvm/test/MC/CSKY/tls_ld.s new file mode 100644 index 000000000000..c4cbf15dfd81 --- /dev/null +++ b/llvm/test/MC/CSKY/tls_ld.s @@ -0,0 +1,29 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3 < %s \ +# RUN: | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + +.LTLS0: + lrw16 r0, xxx@TLSLDM32 + grs32 r2, .LTLS0 + addu16 r0, r0, r2 + lrw16 r3, __tls_get_addr@PLT + ldr32.w r3, (rgb, r3 << 0) + jsr16 r3 + lrw16 r3, xxx@TLSLDO32 + str32.w r4, (r0, r3 << 0) + +# CHECK: 0: lrw16 r0, 0x18 <$d.0> +# CHECK-NEXT: 2: grs32 r2, 0x0 +# CHECK-NEXT: 6: addu16 r0, r0, r2 +# CHECK-NEXT: 8: lrw16 r3, 0x1c <$d.0+0x4> +# CHECK-NEXT: a: ldr32.w r3, (r28, r3 << 0) +# CHECK-NEXT: e: jsr16 r3 +# CHECK-NEXT: 10: lrw16 r3, 0x20 <$d.0+0x8> +# CHECK-NEXT: 12: str32.w r4, (r0, r3 << 0) +# CHECK-NEXT: 16: bkpt + +# CHECK: 18: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000018: R_CKCORE_TLS_LDM32 xxx+0x18 +# CHECK-NEXT: 1c: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 0000001c: R_CKCORE_PLT32 __tls_get_addr +# CHECK-NEXT: 20: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 00000020: R_CKCORE_TLS_LDO32 xxx diff --git a/llvm/test/MC/CSKY/tls_le.s b/llvm/test/MC/CSKY/tls_le.s new file mode 100644 index 000000000000..3206643ef255 --- /dev/null +++ b/llvm/test/MC/CSKY/tls_le.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc -filetype=obj -triple=csky -mattr=+2e3 < %s \ +# RUN: | llvm-objdump --mattr=+2e3 --no-show-raw-insn -M no-aliases -d -r - | FileCheck %s + + lrw16 r3, xxx@TPOFF + lsli32 r2, r31, 0 + str32.w r0, (r2, r3 << 0) + +# CHECK: 0: lrw16 r3, 0xc <$d.0> +# CHECK-NEXT: 2: lsli32 r2, r31, 0 +# CHECK-NEXT: 6: str32.w r0, (r2, r3 << 0) +# CHECK-NEXT: a: bkpt + +# CHECK: c: 00 00 00 00 .word 0x00000000 +# CHECK-NEXT: 0000000c: R_CKCORE_TLS_LE32 xxx diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index c8c512659f4b..a9ce463c22bb 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -441,8 +441,13 @@ static bool isArmElf(const ObjectFile *Obj) { return Elf && Elf->getEMachine() == ELF::EM_ARM; } +static bool isCSKYElf(const ObjectFile *Obj) { + const auto *Elf = dyn_cast(Obj); + return Elf && Elf->getEMachine() == ELF::EM_CSKY; +} + static bool hasMappingSymbols(const ObjectFile *Obj) { - return isArmElf(Obj) || isAArch64Elf(Obj); + return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ; } static void printRelocation(formatted_raw_ostream &OS, StringRef FileName, -- 2.34.1