10b57cec5SDimitry Andric //===-- PPCMCExpr.cpp - PPC specific MC expression classes ----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "PPCMCExpr.h" 100b57cec5SDimitry Andric #include "PPCFixupKinds.h" 110b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 120b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 130b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric using namespace llvm; 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #define DEBUG_TYPE "ppcmcexpr" 190b57cec5SDimitry Andric 205ffd83dbSDimitry Andric const PPCMCExpr *PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr, 215ffd83dbSDimitry Andric MCContext &Ctx) { 225ffd83dbSDimitry Andric return new (Ctx) PPCMCExpr(Kind, Expr); 230b57cec5SDimitry Andric } 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 260b57cec5SDimitry Andric getSubExpr()->print(OS, MAI); 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric switch (Kind) { 295ffd83dbSDimitry Andric default: 305ffd83dbSDimitry Andric llvm_unreachable("Invalid kind!"); 315ffd83dbSDimitry Andric case VK_PPC_LO: 325ffd83dbSDimitry Andric OS << "@l"; 335ffd83dbSDimitry Andric break; 345ffd83dbSDimitry Andric case VK_PPC_HI: 355ffd83dbSDimitry Andric OS << "@h"; 365ffd83dbSDimitry Andric break; 375ffd83dbSDimitry Andric case VK_PPC_HA: 385ffd83dbSDimitry Andric OS << "@ha"; 395ffd83dbSDimitry Andric break; 405ffd83dbSDimitry Andric case VK_PPC_HIGH: 415ffd83dbSDimitry Andric OS << "@high"; 425ffd83dbSDimitry Andric break; 435ffd83dbSDimitry Andric case VK_PPC_HIGHA: 445ffd83dbSDimitry Andric OS << "@higha"; 455ffd83dbSDimitry Andric break; 465ffd83dbSDimitry Andric case VK_PPC_HIGHER: 475ffd83dbSDimitry Andric OS << "@higher"; 485ffd83dbSDimitry Andric break; 495ffd83dbSDimitry Andric case VK_PPC_HIGHERA: 505ffd83dbSDimitry Andric OS << "@highera"; 515ffd83dbSDimitry Andric break; 525ffd83dbSDimitry Andric case VK_PPC_HIGHEST: 535ffd83dbSDimitry Andric OS << "@highest"; 545ffd83dbSDimitry Andric break; 555ffd83dbSDimitry Andric case VK_PPC_HIGHESTA: 565ffd83dbSDimitry Andric OS << "@highesta"; 575ffd83dbSDimitry Andric break; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric bool 620b57cec5SDimitry Andric PPCMCExpr::evaluateAsConstant(int64_t &Res) const { 630b57cec5SDimitry Andric MCValue Value; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr)) 660b57cec5SDimitry Andric return false; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric if (!Value.isAbsolute()) 690b57cec5SDimitry Andric return false; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric Res = evaluateAsInt64(Value.getConstant()); 720b57cec5SDimitry Andric return true; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric int64_t 760b57cec5SDimitry Andric PPCMCExpr::evaluateAsInt64(int64_t Value) const { 770b57cec5SDimitry Andric switch (Kind) { 780b57cec5SDimitry Andric case VK_PPC_LO: 790b57cec5SDimitry Andric return Value & 0xffff; 800b57cec5SDimitry Andric case VK_PPC_HI: 810b57cec5SDimitry Andric return (Value >> 16) & 0xffff; 820b57cec5SDimitry Andric case VK_PPC_HA: 830b57cec5SDimitry Andric return ((Value + 0x8000) >> 16) & 0xffff; 840b57cec5SDimitry Andric case VK_PPC_HIGH: 850b57cec5SDimitry Andric return (Value >> 16) & 0xffff; 860b57cec5SDimitry Andric case VK_PPC_HIGHA: 870b57cec5SDimitry Andric return ((Value + 0x8000) >> 16) & 0xffff; 880b57cec5SDimitry Andric case VK_PPC_HIGHER: 890b57cec5SDimitry Andric return (Value >> 32) & 0xffff; 900b57cec5SDimitry Andric case VK_PPC_HIGHERA: 910b57cec5SDimitry Andric return ((Value + 0x8000) >> 32) & 0xffff; 920b57cec5SDimitry Andric case VK_PPC_HIGHEST: 930b57cec5SDimitry Andric return (Value >> 48) & 0xffff; 940b57cec5SDimitry Andric case VK_PPC_HIGHESTA: 950b57cec5SDimitry Andric return ((Value + 0x8000) >> 48) & 0xffff; 960b57cec5SDimitry Andric case VK_PPC_None: 970b57cec5SDimitry Andric break; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric llvm_unreachable("Invalid kind!"); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 102*0fca6ea1SDimitry Andric bool PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 1030b57cec5SDimitry Andric const MCFixup *Fixup) const { 1040b57cec5SDimitry Andric MCValue Value; 1050b57cec5SDimitry Andric 106*0fca6ea1SDimitry Andric if (!getSubExpr()->evaluateAsRelocatable(Value, Asm, Fixup)) 1070b57cec5SDimitry Andric return false; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric if (Value.isAbsolute()) { 1100b57cec5SDimitry Andric int64_t Result = evaluateAsInt64(Value.getConstant()); 1113a9a9c0cSDimitry Andric bool IsHalf16 = Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16; 1123a9a9c0cSDimitry Andric bool IsHalf16DS = 1133a9a9c0cSDimitry Andric Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16ds; 1143a9a9c0cSDimitry Andric bool IsHalf16DQ = 1153a9a9c0cSDimitry Andric Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16dq; 1163a9a9c0cSDimitry Andric bool IsHalf = IsHalf16 || IsHalf16DS || IsHalf16DQ; 1173a9a9c0cSDimitry Andric 1183a9a9c0cSDimitry Andric if (!IsHalf && Result >= 0x8000) 1190b57cec5SDimitry Andric return false; 1203a9a9c0cSDimitry Andric if ((IsHalf16DS && (Result & 0x3)) || (IsHalf16DQ && (Result & 0xf))) 1213a9a9c0cSDimitry Andric return false; 1223a9a9c0cSDimitry Andric 1230b57cec5SDimitry Andric Res = MCValue::get(Result); 1240b57cec5SDimitry Andric } else { 125*0fca6ea1SDimitry Andric if (!Asm || !Asm->hasLayout()) 1260b57cec5SDimitry Andric return false; 1270b57cec5SDimitry Andric 128*0fca6ea1SDimitry Andric MCContext &Context = Asm->getContext(); 1290b57cec5SDimitry Andric const MCSymbolRefExpr *Sym = Value.getSymA(); 1300b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Modifier = Sym->getKind(); 1310b57cec5SDimitry Andric if (Modifier != MCSymbolRefExpr::VK_None) 1320b57cec5SDimitry Andric return false; 1330b57cec5SDimitry Andric switch (Kind) { 1340b57cec5SDimitry Andric default: 1350b57cec5SDimitry Andric llvm_unreachable("Invalid kind!"); 1360b57cec5SDimitry Andric case VK_PPC_LO: 1370b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_LO; 1380b57cec5SDimitry Andric break; 1390b57cec5SDimitry Andric case VK_PPC_HI: 1400b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_HI; 1410b57cec5SDimitry Andric break; 1420b57cec5SDimitry Andric case VK_PPC_HA: 1430b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_HA; 1440b57cec5SDimitry Andric break; 1450b57cec5SDimitry Andric case VK_PPC_HIGH: 1460b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_HIGH; 1470b57cec5SDimitry Andric break; 1480b57cec5SDimitry Andric case VK_PPC_HIGHA: 1490b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_HIGHA; 1500b57cec5SDimitry Andric break; 1510b57cec5SDimitry Andric case VK_PPC_HIGHERA: 1520b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA; 1530b57cec5SDimitry Andric break; 1540b57cec5SDimitry Andric case VK_PPC_HIGHER: 1550b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_HIGHER; 1560b57cec5SDimitry Andric break; 1570b57cec5SDimitry Andric case VK_PPC_HIGHEST: 1580b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST; 1590b57cec5SDimitry Andric break; 1600b57cec5SDimitry Andric case VK_PPC_HIGHESTA: 1610b57cec5SDimitry Andric Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA; 1620b57cec5SDimitry Andric break; 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context); 1650b57cec5SDimitry Andric Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric return true; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 1720b57cec5SDimitry Andric Streamer.visitUsedExpr(*getSubExpr()); 1730b57cec5SDimitry Andric } 174