xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
create(VariantKind Kind,const MCExpr * Expr,MCContext & Ctx)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 
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const250b57cec5SDimitry 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
evaluateAsConstant(int64_t & Res) const620b57cec5SDimitry 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
evaluateAsInt64(int64_t Value) const760b57cec5SDimitry 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 
evaluateAsRelocatableImpl(MCValue & Res,const MCAssembler * Asm,const MCFixup * Fixup) const102*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 
visitUsedExpr(MCStreamer & Streamer) const1710b57cec5SDimitry Andric void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
1720b57cec5SDimitry Andric   Streamer.visitUsedExpr(*getSubExpr());
1730b57cec5SDimitry Andric }
174