Index: llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp =================================================================== --- llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -42,7 +42,7 @@ return (Value >> 2) & 0x7ffff; case Sparc::fixup_sparc_br16_2: - return (Value >> 2) & 0xc000; + return (Value >> 16) & 0x3; case Sparc::fixup_sparc_br16_14: return (Value >> 2) & 0x3fff; @@ -345,9 +345,16 @@ if (Fixup.getKind() >= FirstLiteralRelocationKind) return; + MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); Value = adjustFixupValue(Fixup.getKind(), Value); if (!Value) return; // Doesn't change encoding. + // Shift the value into position. + if (Endian == support::little) + Value <<= Info.TargetOffset; + else + Value <<= 32 - Info.TargetOffset - Info.TargetSize; + unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); unsigned Offset = Fixup.getOffset(); // For each byte of the fragment that the fixup touches, mask in the bits Index: llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp =================================================================== --- llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -10,6 +10,7 @@ #include "MCTargetDesc/SparcMCExpr.h" #include "MCTargetDesc/SparcMCTargetDesc.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" @@ -62,6 +63,14 @@ case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30; case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22; case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19; + case Sparc::fixup_sparc_br16_14: + return ELF::R_SPARC_WDISP16; + case Sparc::fixup_sparc_br16_2: + // fixup_sparc_br16_14/fixup_sparc_br16_2 are always + // emitted in pairs, but since there's no ELF relocation for + // split bits, emit the real relocation in the _14 part + // and here, in the _2 part, emit an R_SPARC_NONE instead. + return ELF::R_SPARC_NONE; case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22; case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10; case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30; Index: llvm/test/MC/Sparc/sparc64-bpr-offset.s =================================================================== --- /dev/null +++ llvm/test/MC/Sparc/sparc64-bpr-offset.s @@ -0,0 +1,31 @@ +! RUN: llvm-mc -arch=sparcv9 -filetype=obj %s | llvm-objdump -d - | FileCheck %s --check-prefix=BIN + + !! SPARCv9/SPARC64 BPr branches have different offset encoding for the others, + !! make sure that our offset bits don't trample on other fields. + !! This is particularly important with backwards branches. + + ! BIN: 0: 02 c8 40 01 brz %g1, 1 + ! BIN: 4: 04 c8 40 01 brlez %g1, 1 + ! BIN: 8: 06 c8 40 01 brlz %g1, 1 + ! BIN: c: 0a c8 40 01 brnz %g1, 1 + ! BIN: 10: 0c c8 40 01 brgz %g1, 1 + ! BIN: 14: 0e c8 40 01 brgez %g1, 1 + brz %g1, .+4 + brlez %g1, .+4 + brlz %g1, .+4 + brnz %g1, .+4 + brgz %g1, .+4 + brgez %g1, .+4 + + ! BIN: 18: 02 f8 7f ff brz %g1, 65535 + ! BIN: 1c: 04 f8 7f ff brlez %g1, 65535 + ! BIN: 20: 06 f8 7f ff brlz %g1, 65535 + ! BIN: 24: 0a f8 7f ff brnz %g1, 65535 + ! BIN: 28: 0c f8 7f ff brgz %g1, 65535 + ! BIN: 2c: 0e f8 7f ff brgez %g1, 65535 + brz %g1, .-4 + brlez %g1, .-4 + brlz %g1, .-4 + brnz %g1, .-4 + brgz %g1, .-4 + brgez %g1, .-4