From 84491abb201a2df0fadf7654e0912cb0d42a4874 Mon Sep 17 00:00:00 2001 From: Jack Carter Date: Mon, 6 Aug 2012 21:26:03 +0000 Subject: [PATCH] Mips relocations R_MIPS_HIGHER and R_MIPS_HIGHEST. These 2 relocations gain access to the highest and the second highest 16 bits of a 64 bit object. R_MIPS_HIGHER %higher(A+S) The %higher(x) function is [ (((long long) x + 0x80008000LL) >> 32) & 0xffff ]. R_MIPS_HIGHEST %highest(A+S) The %highest(x) function is [ (((long long) x + 0x800080008000LL) >> 48) & 0xffff ]. llvm-svn: 161348 --- .../Mips/MCTargetDesc/MipsAsmBackend.cpp | 14 ++++++++-- .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 6 +++++ .../Target/Mips/MCTargetDesc/MipsFixupKinds.h | 6 +++++ .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 6 +++++ llvm/test/MC/Mips/higher_highest.ll | 27 +++++++++++++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 llvm/test/MC/Mips/higher_highest.ll diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 6fe0c11911d1..f679b6f90995 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -59,9 +59,17 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { break; case Mips::fixup_Mips_HI16: case Mips::fixup_Mips_GOT_Local: - // Get the higher 16-bits. Also add 1 if bit 15 is 1. + // Get the 2nd 16-bits. Also add 1 if bit 15 is 1. Value = ((Value + 0x8000) >> 16) & 0xffff; break; + case Mips::fixup_Mips_HIGHER: + // Get the 3rd 16-bits. + Value = ((Value + 0x80008000LL) >> 32) & 0xffff; + break; + case Mips::fixup_Mips_HIGHEST: + // Get the 4th 16-bits. + Value = ((Value + 0x800080008000LL) >> 48) & 0xffff; + break; } return Value; @@ -168,7 +176,9 @@ public: { "fixup_Mips_GPOFF_LO", 0, 16, 0 }, { "fixup_Mips_GOT_PAGE", 0, 16, 0 }, { "fixup_Mips_GOT_OFST", 0, 16, 0 }, - { "fixup_Mips_GOT_DISP", 0, 16, 0 } + { "fixup_Mips_GOT_DISP", 0, 16, 0 }, + { "fixup_Mips_HIGHER", 0, 16, 0 }, + { "fixup_Mips_HIGHEST", 0, 16, 0 } }; if (Kind < FirstTargetFixupKind) diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 77c1524531c3..1ff304494e7e 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -169,6 +169,12 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); break; + case Mips::fixup_Mips_HIGHER: + Type = ELF::R_MIPS_HIGHER; + break; + case Mips::fixup_Mips_HIGHEST: + Type = ELF::R_MIPS_HIGHEST; + break; } return Type; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index f5cbbd537d1c..77faec54fb23 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -110,6 +110,12 @@ namespace Mips { // resulting in - R_MIPS_GOT_DISP fixup_Mips_GOT_DISP, + // resulting in - R_MIPS_GOT_HIGHER + fixup_Mips_HIGHER, + + // resulting in - R_MIPS_HIGHEST + fixup_Mips_HIGHEST, + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index ff3b3a7ed1c2..8dab62d51813 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -255,6 +255,12 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, case MCSymbolRefExpr::VK_Mips_TPREL_LO: FixupKind = Mips::fixup_Mips_TPREL_LO; break; + case MCSymbolRefExpr::VK_Mips_HIGHER: + FixupKind = Mips::fixup_Mips_HIGHER; + break; + case MCSymbolRefExpr::VK_Mips_HIGHEST: + FixupKind = Mips::fixup_Mips_HIGHEST; + break; } // switch Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind))); diff --git a/llvm/test/MC/Mips/higher_highest.ll b/llvm/test/MC/Mips/higher_highest.ll new file mode 100644 index 000000000000..81a89e3040e3 --- /dev/null +++ b/llvm/test/MC/Mips/higher_highest.ll @@ -0,0 +1,27 @@ +; RUN: llc -march=mips64el -mcpu=mips64 -mattr=n64 -force-mips-long-branch -filetype=obj < %s -o - | elf-dump --dump-section-data | FileCheck %s + +; Check that the R_MIPS_HIGHER and R_MIPS_HIGHEST relocations were created. + +; CHECK: ('r_type', 0x1d) +; CHECK: ('r_type', 0x1d) +; CHECK: ('r_type', 0x1c) +; CHECK: ('r_type', 0x1c) + +@g0 = external global i32 + +define void @foo1(i32 %s) nounwind { +entry: + + %tobool = icmp eq i32 %s, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + %0 = load i32* @g0, align 4 + %add = add nsw i32 %0, 12 + store i32 %add, i32* @g0, align 4 + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +} +