223 lines · cpp
1//===-- AVRMCAsmInfo.cpp - AVR asm properties -----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the declarations of the AVRMCAsmInfo properties.10//11//===----------------------------------------------------------------------===//12 13#include "AVRMCAsmInfo.h"14#include "llvm/MC/MCAssembler.h"15#include "llvm/MC/MCContext.h"16#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCValue.h"18#include "llvm/TargetParser/Triple.h"19 20using namespace llvm;21 22AVRMCAsmInfo::AVRMCAsmInfo(const Triple &TT, const MCTargetOptions &Options) {23 CodePointerSize = 2;24 CalleeSaveStackSlotSize = 2;25 CommentString = ";";26 SeparatorString = "$";27 UsesELFSectionDirectiveForBSS = true;28 SupportsDebugInformation = true;29}30 31namespace {32const struct ModifierEntry {33 const char *const Spelling;34 AVRMCExpr::Specifier specifier;35} ModifierNames[] = {36 {"lo8", AVR::S_LO8}, {"hi8", AVR::S_HI8},37 {"hh8", AVR::S_HH8}, // synonym with hlo838 {"hlo8", AVR::S_HH8}, {"hhi8", AVR::S_HHI8},39 40 {"pm", AVR::S_PM}, {"pm_lo8", AVR::S_PM_LO8},41 {"pm_hi8", AVR::S_PM_HI8}, {"pm_hh8", AVR::S_PM_HH8},42 43 {"lo8_gs", AVR::S_LO8_GS}, {"hi8_gs", AVR::S_HI8_GS},44 {"gs", AVR::S_GS},45};46 47} // end of anonymous namespace48 49AVRMCExpr::Specifier AVRMCExpr::parseSpecifier(StringRef Name) {50 const auto &Modifier =51 llvm::find_if(ModifierNames, [&Name](ModifierEntry const &Mod) {52 return Mod.Spelling == Name;53 });54 55 if (Modifier != std::end(ModifierNames)) {56 return Modifier->specifier;57 }58 return AVR::S_AVR_NONE;59}60 61const char *AVRMCExpr::getName() const {62 const auto &Modifier =63 llvm::find_if(ModifierNames, [this](ModifierEntry const &Mod) {64 return Mod.specifier == getSpecifier();65 });66 67 if (Modifier != std::end(ModifierNames)) {68 return Modifier->Spelling;69 }70 return nullptr;71}72 73AVR::Fixups AVRMCExpr::getFixupKind() const {74 AVR::Fixups Kind = AVR::Fixups::LastTargetFixupKind;75 76 switch (getSpecifier()) {77 case AVR::S_LO8:78 Kind = isNegated() ? AVR::fixup_lo8_ldi_neg : AVR::fixup_lo8_ldi;79 break;80 case AVR::S_HI8:81 Kind = isNegated() ? AVR::fixup_hi8_ldi_neg : AVR::fixup_hi8_ldi;82 break;83 case AVR::S_HH8:84 Kind = isNegated() ? AVR::fixup_hh8_ldi_neg : AVR::fixup_hh8_ldi;85 break;86 case AVR::S_HHI8:87 Kind = isNegated() ? AVR::fixup_ms8_ldi_neg : AVR::fixup_ms8_ldi;88 break;89 90 case AVR::S_PM_LO8:91 Kind = isNegated() ? AVR::fixup_lo8_ldi_pm_neg : AVR::fixup_lo8_ldi_pm;92 break;93 case AVR::S_PM_HI8:94 Kind = isNegated() ? AVR::fixup_hi8_ldi_pm_neg : AVR::fixup_hi8_ldi_pm;95 break;96 case AVR::S_PM_HH8:97 Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm;98 break;99 case AVR::S_PM:100 case AVR::S_GS:101 Kind = AVR::fixup_16_pm;102 break;103 case AVR::S_LO8_GS:104 Kind = AVR::fixup_lo8_ldi_gs;105 break;106 case AVR::S_HI8_GS:107 Kind = AVR::fixup_hi8_ldi_gs;108 break;109 110 default:111 llvm_unreachable("Uninitialized expression");112 }113 114 return Kind;115}116 117void AVRMCAsmInfo::printSpecifierExpr(raw_ostream &OS,118 const MCSpecifierExpr &Expr) const {119 auto &E = static_cast<const AVRMCExpr &>(Expr);120 assert(E.getSpecifier() != AVR::S_AVR_NONE);121 OS << E.getName() << '(';122 if (E.isNegated())123 OS << '-' << '(';124 printExpr(OS, *E.getSubExpr());125 if (E.isNegated())126 OS << ')';127 OS << ')';128}129 130int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const {131 if (Negated)132 Value *= -1;133 134 switch (getSpecifier()) {135 case AVR::S_LO8:136 Value &= 0xff;137 break;138 case AVR::S_HI8:139 Value &= 0xff00;140 Value >>= 8;141 break;142 case AVR::S_HH8:143 Value &= 0xff0000;144 Value >>= 16;145 break;146 case AVR::S_HHI8:147 Value &= 0xff000000;148 Value >>= 24;149 break;150 case AVR::S_PM_LO8:151 case AVR::S_LO8_GS:152 Value >>= 1; // Program memory addresses must always be shifted by one.153 Value &= 0xff;154 break;155 case AVR::S_PM_HI8:156 case AVR::S_HI8_GS:157 Value >>= 1; // Program memory addresses must always be shifted by one.158 Value &= 0xff00;159 Value >>= 8;160 break;161 case AVR::S_PM_HH8:162 Value >>= 1; // Program memory addresses must always be shifted by one.163 Value &= 0xff0000;164 Value >>= 16;165 break;166 case AVR::S_PM:167 case AVR::S_GS:168 Value >>= 1; // Program memory addresses must always be shifted by one.169 break;170 171 case AVR::S_AVR_NONE:172 default:173 llvm_unreachable("Uninitialized expression.");174 }175 return static_cast<uint64_t>(Value) & 0xff;176}177 178// bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result,179// const MCAssembler *Asm) const {180bool AVRMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr,181 MCValue &Result,182 const MCAssembler *Asm) const {183 auto &E = static_cast<const AVRMCExpr &>(Expr);184 MCValue Value;185 bool isRelocatable = E.getSubExpr()->evaluateAsRelocatable(Value, Asm);186 if (!isRelocatable)187 return false;188 189 if (Value.isAbsolute()) {190 Result = MCValue::get(E.evaluateAsInt64(Value.getConstant()));191 } else {192 if (!Asm || !Asm->hasLayout())193 return false;194 195 auto Spec = AVR::S_None;196 if (Value.getSpecifier())197 return false;198 assert(!Value.getSubSym());199 if (E.getSpecifier() == AVR::S_PM)200 Spec = AVR::S_PM;201 202 // TODO: don't attach specifier to MCSymbolRefExpr.203 Result =204 MCValue::get(Value.getAddSym(), nullptr, Value.getConstant(), Spec);205 }206 207 return true;208}209 210bool AVRMCExpr::evaluateAsConstant(int64_t &Result) const {211 MCValue Value;212 bool isRelocatable = getSubExpr()->evaluateAsRelocatable(Value, nullptr);213 if (!isRelocatable)214 return false;215 216 if (Value.isAbsolute()) {217 Result = evaluateAsInt64(Value.getConstant());218 return true;219 }220 221 return false;222}223