diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 8e03b86ff6c..99ccbbdc29d 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -174,6 +174,10 @@ public: VK_PPC_LO, // symbol@l VK_PPC_HI, // symbol@h VK_PPC_HA, // symbol@ha + VK_PPC_HIGHER, // symbol@higher + VK_PPC_HIGHERA, // symbol@highera + VK_PPC_HIGHEST, // symbol@highest + VK_PPC_HIGHESTA, // symbol@highesta VK_PPC_TOCBASE, // symbol@tocbase VK_PPC_TOC, // symbol@toc VK_PPC_TOC_LO, // symbol@toc@l diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 507791bd738..e21de69b5ce 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -2053,7 +2053,9 @@ StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHERA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHESTA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 7aba542dc27..23484f4b5f3 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -484,7 +484,9 @@ enum { R_PPC64_REL32 = 26, R_PPC64_ADDR64 = 38, R_PPC64_ADDR16_HIGHER = 39, + R_PPC64_ADDR16_HIGHERA = 40, R_PPC64_ADDR16_HIGHEST = 41, + R_PPC64_ADDR16_HIGHESTA = 42, R_PPC64_REL64 = 44, R_PPC64_TOC16 = 47, R_PPC64_TOC16_LO = 48, diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 454965a3a8a..17da6796c4f 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -199,6 +199,10 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_PPC_LO: return "l"; case VK_PPC_HI: return "h"; case VK_PPC_HA: return "ha"; + case VK_PPC_HIGHER: return "higher"; + case VK_PPC_HIGHERA: return "highera"; + case VK_PPC_HIGHEST: return "highest"; + case VK_PPC_HIGHESTA: return "highesta"; case VK_PPC_TOCBASE: return "tocbase"; case VK_PPC_TOC: return "toc"; case VK_PPC_TOC_LO: return "toc@l"; @@ -287,6 +291,14 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("h", VK_PPC_HI) .Case("HA", VK_PPC_HA) .Case("ha", VK_PPC_HA) + .Case("HIGHER", VK_PPC_HIGHER) + .Case("higher", VK_PPC_HIGHER) + .Case("HIGHERA", VK_PPC_HIGHERA) + .Case("highera", VK_PPC_HIGHERA) + .Case("HIGHEST", VK_PPC_HIGHEST) + .Case("highest", VK_PPC_HIGHEST) + .Case("HIGHESTA", VK_PPC_HIGHESTA) + .Case("highesta", VK_PPC_HIGHESTA) .Case("TOCBASE", VK_PPC_TOCBASE) .Case("tocbase", VK_PPC_TOCBASE) .Case("TOC", VK_PPC_TOC) diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 964f2722833..6318d416f5e 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -575,6 +575,18 @@ ExtractModifierFromExpr(const MCExpr *E, case MCSymbolRefExpr::VK_PPC_HA: Variant = PPCMCExpr::VK_PPC_HA; break; + case MCSymbolRefExpr::VK_PPC_HIGHER: + Variant = PPCMCExpr::VK_PPC_HIGHER; + break; + case MCSymbolRefExpr::VK_PPC_HIGHERA: + Variant = PPCMCExpr::VK_PPC_HIGHERA; + break; + case MCSymbolRefExpr::VK_PPC_HIGHEST: + Variant = PPCMCExpr::VK_PPC_HIGHEST; + break; + case MCSymbolRefExpr::VK_PPC_HIGHESTA: + Variant = PPCMCExpr::VK_PPC_HIGHESTA; + break; default: return 0; } diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index ed775295492..7a95bcc00be 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -96,6 +96,18 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PPC_HA: Type = ELF::R_PPC_ADDR16_HA; break; + case MCSymbolRefExpr::VK_PPC_HIGHER: + Type = ELF::R_PPC64_ADDR16_HIGHER; + break; + case MCSymbolRefExpr::VK_PPC_HIGHERA: + Type = ELF::R_PPC64_ADDR16_HIGHERA; + break; + case MCSymbolRefExpr::VK_PPC_HIGHEST: + Type = ELF::R_PPC64_ADDR16_HIGHEST; + break; + case MCSymbolRefExpr::VK_PPC_HIGHESTA: + Type = ELF::R_PPC64_ADDR16_HIGHESTA; + break; case MCSymbolRefExpr::VK_PPC_TOC: Type = ELF::R_PPC64_TOC16; break; diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp index 8a346b422d2..db0f57dfb3a 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp @@ -42,6 +42,10 @@ void PPCMCExpr::PrintImpl(raw_ostream &OS) const { case VK_PPC_LO: OS << "@l"; break; case VK_PPC_HI: OS << "@h"; break; case VK_PPC_HA: OS << "@ha"; break; + case VK_PPC_HIGHER: OS << "@higher"; break; + case VK_PPC_HIGHERA: OS << "@highera"; break; + case VK_PPC_HIGHEST: OS << "@highest"; break; + case VK_PPC_HIGHESTA: OS << "@highesta"; break; } } } @@ -66,7 +70,19 @@ PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, Result = (Result >> 16) & 0xffff; break; case VK_PPC_HA: - Result = ((Result >> 16) + ((Result & 0x8000) ? 1 : 0)) & 0xffff; + Result = ((Result + 0x8000) >> 16) & 0xffff; + break; + case VK_PPC_HIGHER: + Result = (Result >> 32) & 0xffff; + break; + case VK_PPC_HIGHERA: + Result = ((Result + 0x8000) >> 32) & 0xffff; + break; + case VK_PPC_HIGHEST: + Result = (Result >> 48) & 0xffff; + break; + case VK_PPC_HIGHESTA: + Result = ((Result + 0x8000) >> 48) & 0xffff; break; } Res = MCValue::get(Result); @@ -88,6 +104,18 @@ PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, case VK_PPC_HA: Modifier = MCSymbolRefExpr::VK_PPC_HA; break; + case VK_PPC_HIGHERA: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA; + break; + case VK_PPC_HIGHER: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHER; + break; + case VK_PPC_HIGHEST: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST; + break; + case VK_PPC_HIGHESTA: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA; + break; } Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context); Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h index 150acf60529..3cbb493bc6b 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h @@ -22,7 +22,11 @@ public: VK_PPC_None, VK_PPC_LO, VK_PPC_HI, - VK_PPC_HA + VK_PPC_HA, + VK_PPC_HIGHER, + VK_PPC_HIGHERA, + VK_PPC_HIGHEST, + VK_PPC_HIGHESTA }; private: diff --git a/test/MC/PowerPC/ppc64-fixup-apply.s b/test/MC/PowerPC/ppc64-fixup-apply.s index 50f74bf98dc..8d3a980116b 100644 --- a/test/MC/PowerPC/ppc64-fixup-apply.s +++ b/test/MC/PowerPC/ppc64-fixup-apply.s @@ -38,6 +38,13 @@ addis 1, 1, target6@h .set target6, 0x4321fedc +addi 1, 1, target7@higher +addis 1, 1, target7@highest +addi 1, 1, target7@highera +addis 1, 1, target7@highesta + +.set target7, 0x1234ffffffff8000 + .data .quad v1 @@ -59,7 +66,7 @@ addis 1, 1, target6@h # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 # CHECK-NEXT: Offset: -# CHECK-NEXT: Size: 48 +# CHECK-NEXT: Size: 64 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 # CHECK-NEXT: AddressAlignment: 4 @@ -68,6 +75,7 @@ addis 1, 1, target6@h # CHECK-NEXT: 0000: 38211234 3C211234 38215678 3C211234 # CHECK-NEXT: 0010: 38214444 3C211111 38218001 3C211001 # CHECK-NEXT: 0020: 38210008 3C210000 38214321 3C214321 +# CHECK-NEXT: 0030: 3821FFFF 3C211234 38210000 3C211235 # CHECK-NEXT: ) # CHECK-NEXT: } diff --git a/test/MC/PowerPC/ppc64-fixups.s b/test/MC/PowerPC/ppc64-fixups.s index 9accde047c6..1b424d3a4ba 100644 --- a/test/MC/PowerPC/ppc64-fixups.s +++ b/test/MC/PowerPC/ppc64-fixups.s @@ -57,6 +57,26 @@ # CHECK-REL: 0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_HI target 0x0 lis 3, target@h +# CHECK: li 3, target@higher # encoding: [0x38,0x60,A,A] +# CHECK-NEXT: # fixup A - offset: 2, value: target@higher, kind: fixup_ppc_half16 +# CHECK-REL: 0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_HIGHER target 0x0 + li 3, target@higher + +# CHECK: lis 3, target@highest # encoding: [0x3c,0x60,A,A] +# CHECK-NEXT: # fixup A - offset: 2, value: target@highest, kind: fixup_ppc_half16 +# CHECK-REL: 0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_HIGHEST target 0x0 + lis 3, target@highest + +# CHECK: li 3, target@highera # encoding: [0x38,0x60,A,A] +# CHECK-NEXT: # fixup A - offset: 2, value: target@highera, kind: fixup_ppc_half16 +# CHECK-REL: 0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_HIGHERA target 0x0 + li 3, target@highera + +# CHECK: lis 3, target@highesta # encoding: [0x3c,0x60,A,A] +# CHECK-NEXT: # fixup A - offset: 2, value: target@highesta, kind: fixup_ppc_half16 +# CHECK-REL: 0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_HIGHESTA target 0x0 + lis 3, target@highesta + # CHECK: lwz 1, target@l(3) # encoding: [0x80,0x23,A,A] # CHECK-NEXT: # fixup A - offset: 2, value: target@l, kind: fixup_ppc_half16 # CHECK-REL: 0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_LO target 0x0