10b57cec5SDimitry Andric //===-- AVRMCExpr.cpp - AVR 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 "AVRMCExpr.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
120b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric namespace {
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric const struct ModifierEntry {
210b57cec5SDimitry Andric const char *const Spelling;
220b57cec5SDimitry Andric AVRMCExpr::VariantKind VariantKind;
230b57cec5SDimitry Andric } ModifierNames[] = {
240b57cec5SDimitry Andric {"lo8", AVRMCExpr::VK_AVR_LO8}, {"hi8", AVRMCExpr::VK_AVR_HI8},
250b57cec5SDimitry Andric {"hh8", AVRMCExpr::VK_AVR_HH8}, // synonym with hlo8
260b57cec5SDimitry Andric {"hlo8", AVRMCExpr::VK_AVR_HH8}, {"hhi8", AVRMCExpr::VK_AVR_HHI8},
270b57cec5SDimitry Andric
28349cc55cSDimitry Andric {"pm", AVRMCExpr::VK_AVR_PM}, {"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8},
29349cc55cSDimitry Andric {"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8}, {"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8},
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric {"lo8_gs", AVRMCExpr::VK_AVR_LO8_GS}, {"hi8_gs", AVRMCExpr::VK_AVR_HI8_GS},
320b57cec5SDimitry Andric {"gs", AVRMCExpr::VK_AVR_GS},
330b57cec5SDimitry Andric };
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric } // end of anonymous namespace
360b57cec5SDimitry Andric
create(VariantKind Kind,const MCExpr * Expr,bool Negated,MCContext & Ctx)370b57cec5SDimitry Andric const AVRMCExpr *AVRMCExpr::create(VariantKind Kind, const MCExpr *Expr,
380b57cec5SDimitry Andric bool Negated, MCContext &Ctx) {
390b57cec5SDimitry Andric return new (Ctx) AVRMCExpr(Kind, Expr, Negated);
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const420b57cec5SDimitry Andric void AVRMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
430b57cec5SDimitry Andric assert(Kind != VK_AVR_None);
440b57cec5SDimitry Andric OS << getName() << '(';
45bdd1243dSDimitry Andric if (isNegated())
46bdd1243dSDimitry Andric OS << '-' << '(';
470b57cec5SDimitry Andric getSubExpr()->print(OS, MAI);
48bdd1243dSDimitry Andric if (isNegated())
49bdd1243dSDimitry Andric OS << ')';
500b57cec5SDimitry Andric OS << ')';
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric
evaluateAsConstant(int64_t & Result) const530b57cec5SDimitry Andric bool AVRMCExpr::evaluateAsConstant(int64_t &Result) const {
540b57cec5SDimitry Andric MCValue Value;
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric bool isRelocatable =
570b57cec5SDimitry Andric getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr);
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric if (!isRelocatable)
600b57cec5SDimitry Andric return false;
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric if (Value.isAbsolute()) {
630b57cec5SDimitry Andric Result = evaluateAsInt64(Value.getConstant());
640b57cec5SDimitry Andric return true;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric return false;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric
evaluateAsRelocatableImpl(MCValue & Result,const MCAssembler * Asm,const MCFixup * Fixup) const700b57cec5SDimitry Andric bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result,
71*0fca6ea1SDimitry Andric const MCAssembler *Asm,
720b57cec5SDimitry Andric const MCFixup *Fixup) const {
730b57cec5SDimitry Andric MCValue Value;
74*0fca6ea1SDimitry Andric bool isRelocatable = SubExpr->evaluateAsRelocatable(Value, Asm, Fixup);
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric if (!isRelocatable)
770b57cec5SDimitry Andric return false;
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric if (Value.isAbsolute()) {
800b57cec5SDimitry Andric Result = MCValue::get(evaluateAsInt64(Value.getConstant()));
810b57cec5SDimitry Andric } else {
82*0fca6ea1SDimitry Andric if (!Asm || !Asm->hasLayout())
83349cc55cSDimitry Andric return false;
840b57cec5SDimitry Andric
85*0fca6ea1SDimitry Andric MCContext &Context = Asm->getContext();
860b57cec5SDimitry Andric const MCSymbolRefExpr *Sym = Value.getSymA();
870b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
880b57cec5SDimitry Andric if (Modifier != MCSymbolRefExpr::VK_None)
890b57cec5SDimitry Andric return false;
90fe6060f1SDimitry Andric if (Kind == VK_AVR_PM) {
91fe6060f1SDimitry Andric Modifier = MCSymbolRefExpr::VK_AVR_PM;
92fe6060f1SDimitry Andric }
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
950b57cec5SDimitry Andric Result = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric return true;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
evaluateAsInt64(int64_t Value) const1010b57cec5SDimitry Andric int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const {
1020b57cec5SDimitry Andric if (Negated)
1030b57cec5SDimitry Andric Value *= -1;
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric switch (Kind) {
1060b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_LO8:
1070b57cec5SDimitry Andric Value &= 0xff;
1080b57cec5SDimitry Andric break;
1090b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_HI8:
1100b57cec5SDimitry Andric Value &= 0xff00;
1110b57cec5SDimitry Andric Value >>= 8;
1120b57cec5SDimitry Andric break;
1130b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_HH8:
1140b57cec5SDimitry Andric Value &= 0xff0000;
1150b57cec5SDimitry Andric Value >>= 16;
1160b57cec5SDimitry Andric break;
1170b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_HHI8:
1180b57cec5SDimitry Andric Value &= 0xff000000;
1190b57cec5SDimitry Andric Value >>= 24;
1200b57cec5SDimitry Andric break;
1210b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_PM_LO8:
1220b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_LO8_GS:
1230b57cec5SDimitry Andric Value >>= 1; // Program memory addresses must always be shifted by one.
1240b57cec5SDimitry Andric Value &= 0xff;
1250b57cec5SDimitry Andric break;
1260b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_PM_HI8:
1270b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_HI8_GS:
1280b57cec5SDimitry Andric Value >>= 1; // Program memory addresses must always be shifted by one.
1290b57cec5SDimitry Andric Value &= 0xff00;
1300b57cec5SDimitry Andric Value >>= 8;
1310b57cec5SDimitry Andric break;
1320b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_PM_HH8:
1330b57cec5SDimitry Andric Value >>= 1; // Program memory addresses must always be shifted by one.
1340b57cec5SDimitry Andric Value &= 0xff0000;
1350b57cec5SDimitry Andric Value >>= 16;
1360b57cec5SDimitry Andric break;
137fe6060f1SDimitry Andric case AVRMCExpr::VK_AVR_PM:
1380b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_GS:
1390b57cec5SDimitry Andric Value >>= 1; // Program memory addresses must always be shifted by one.
1400b57cec5SDimitry Andric break;
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric case AVRMCExpr::VK_AVR_None:
1430b57cec5SDimitry Andric llvm_unreachable("Uninitialized expression.");
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric return static_cast<uint64_t>(Value) & 0xff;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric
getFixupKind() const1480b57cec5SDimitry Andric AVR::Fixups AVRMCExpr::getFixupKind() const {
1490b57cec5SDimitry Andric AVR::Fixups Kind = AVR::Fixups::LastTargetFixupKind;
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andric switch (getKind()) {
1520b57cec5SDimitry Andric case VK_AVR_LO8:
1530b57cec5SDimitry Andric Kind = isNegated() ? AVR::fixup_lo8_ldi_neg : AVR::fixup_lo8_ldi;
1540b57cec5SDimitry Andric break;
1550b57cec5SDimitry Andric case VK_AVR_HI8:
1560b57cec5SDimitry Andric Kind = isNegated() ? AVR::fixup_hi8_ldi_neg : AVR::fixup_hi8_ldi;
1570b57cec5SDimitry Andric break;
1580b57cec5SDimitry Andric case VK_AVR_HH8:
1590b57cec5SDimitry Andric Kind = isNegated() ? AVR::fixup_hh8_ldi_neg : AVR::fixup_hh8_ldi;
1600b57cec5SDimitry Andric break;
1610b57cec5SDimitry Andric case VK_AVR_HHI8:
1620b57cec5SDimitry Andric Kind = isNegated() ? AVR::fixup_ms8_ldi_neg : AVR::fixup_ms8_ldi;
1630b57cec5SDimitry Andric break;
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric case VK_AVR_PM_LO8:
1660b57cec5SDimitry Andric Kind = isNegated() ? AVR::fixup_lo8_ldi_pm_neg : AVR::fixup_lo8_ldi_pm;
1670b57cec5SDimitry Andric break;
1680b57cec5SDimitry Andric case VK_AVR_PM_HI8:
1690b57cec5SDimitry Andric Kind = isNegated() ? AVR::fixup_hi8_ldi_pm_neg : AVR::fixup_hi8_ldi_pm;
1700b57cec5SDimitry Andric break;
1710b57cec5SDimitry Andric case VK_AVR_PM_HH8:
1720b57cec5SDimitry Andric Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm;
1730b57cec5SDimitry Andric break;
174fe6060f1SDimitry Andric case VK_AVR_PM:
1750b57cec5SDimitry Andric case VK_AVR_GS:
1760b57cec5SDimitry Andric Kind = AVR::fixup_16_pm;
1770b57cec5SDimitry Andric break;
1780b57cec5SDimitry Andric case VK_AVR_LO8_GS:
1790b57cec5SDimitry Andric Kind = AVR::fixup_lo8_ldi_gs;
1800b57cec5SDimitry Andric break;
1810b57cec5SDimitry Andric case VK_AVR_HI8_GS:
1820b57cec5SDimitry Andric Kind = AVR::fixup_hi8_ldi_gs;
1830b57cec5SDimitry Andric break;
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric case VK_AVR_None:
1860b57cec5SDimitry Andric llvm_unreachable("Uninitialized expression");
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric return Kind;
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric
visitUsedExpr(MCStreamer & Streamer) const1920b57cec5SDimitry Andric void AVRMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
1930b57cec5SDimitry Andric Streamer.visitUsedExpr(*getSubExpr());
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric
getName() const1960b57cec5SDimitry Andric const char *AVRMCExpr::getName() const {
197e8d8bef9SDimitry Andric const auto &Modifier =
198e8d8bef9SDimitry Andric llvm::find_if(ModifierNames, [this](ModifierEntry const &Mod) {
199e8d8bef9SDimitry Andric return Mod.VariantKind == Kind;
200e8d8bef9SDimitry Andric });
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric if (Modifier != std::end(ModifierNames)) {
2030b57cec5SDimitry Andric return Modifier->Spelling;
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric return nullptr;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric
getKindByName(StringRef Name)2080b57cec5SDimitry Andric AVRMCExpr::VariantKind AVRMCExpr::getKindByName(StringRef Name) {
209e8d8bef9SDimitry Andric const auto &Modifier =
210e8d8bef9SDimitry Andric llvm::find_if(ModifierNames, [&Name](ModifierEntry const &Mod) {
211e8d8bef9SDimitry Andric return Mod.Spelling == Name;
212e8d8bef9SDimitry Andric });
2130b57cec5SDimitry Andric
2140b57cec5SDimitry Andric if (Modifier != std::end(ModifierNames)) {
2150b57cec5SDimitry Andric return Modifier->VariantKind;
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric return VK_AVR_None;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric } // end of namespace llvm
221