223 lines
6.0 KiB
C++
223 lines
6.0 KiB
C++
//===-- AVRMCAsmInfo.cpp - AVR asm properties -----------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the declarations of the AVRMCAsmInfo properties.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "AVRMCAsmInfo.h"
|
|
#include "llvm/MC/MCAssembler.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCExpr.h"
|
|
#include "llvm/MC/MCValue.h"
|
|
#include "llvm/TargetParser/Triple.h"
|
|
|
|
using namespace llvm;
|
|
|
|
AVRMCAsmInfo::AVRMCAsmInfo(const Triple &TT, const MCTargetOptions &Options) {
|
|
CodePointerSize = 2;
|
|
CalleeSaveStackSlotSize = 2;
|
|
CommentString = ";";
|
|
SeparatorString = "$";
|
|
UsesELFSectionDirectiveForBSS = true;
|
|
SupportsDebugInformation = true;
|
|
}
|
|
|
|
namespace {
|
|
const struct ModifierEntry {
|
|
const char *const Spelling;
|
|
AVRMCExpr::Specifier specifier;
|
|
} ModifierNames[] = {
|
|
{"lo8", AVR::S_LO8}, {"hi8", AVR::S_HI8},
|
|
{"hh8", AVR::S_HH8}, // synonym with hlo8
|
|
{"hlo8", AVR::S_HH8}, {"hhi8", AVR::S_HHI8},
|
|
|
|
{"pm", AVR::S_PM}, {"pm_lo8", AVR::S_PM_LO8},
|
|
{"pm_hi8", AVR::S_PM_HI8}, {"pm_hh8", AVR::S_PM_HH8},
|
|
|
|
{"lo8_gs", AVR::S_LO8_GS}, {"hi8_gs", AVR::S_HI8_GS},
|
|
{"gs", AVR::S_GS},
|
|
};
|
|
|
|
} // end of anonymous namespace
|
|
|
|
AVRMCExpr::Specifier AVRMCExpr::parseSpecifier(StringRef Name) {
|
|
const auto &Modifier =
|
|
llvm::find_if(ModifierNames, [&Name](ModifierEntry const &Mod) {
|
|
return Mod.Spelling == Name;
|
|
});
|
|
|
|
if (Modifier != std::end(ModifierNames)) {
|
|
return Modifier->specifier;
|
|
}
|
|
return AVR::S_AVR_NONE;
|
|
}
|
|
|
|
const char *AVRMCExpr::getName() const {
|
|
const auto &Modifier =
|
|
llvm::find_if(ModifierNames, [this](ModifierEntry const &Mod) {
|
|
return Mod.specifier == getSpecifier();
|
|
});
|
|
|
|
if (Modifier != std::end(ModifierNames)) {
|
|
return Modifier->Spelling;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
AVR::Fixups AVRMCExpr::getFixupKind() const {
|
|
AVR::Fixups Kind = AVR::Fixups::LastTargetFixupKind;
|
|
|
|
switch (getSpecifier()) {
|
|
case AVR::S_LO8:
|
|
Kind = isNegated() ? AVR::fixup_lo8_ldi_neg : AVR::fixup_lo8_ldi;
|
|
break;
|
|
case AVR::S_HI8:
|
|
Kind = isNegated() ? AVR::fixup_hi8_ldi_neg : AVR::fixup_hi8_ldi;
|
|
break;
|
|
case AVR::S_HH8:
|
|
Kind = isNegated() ? AVR::fixup_hh8_ldi_neg : AVR::fixup_hh8_ldi;
|
|
break;
|
|
case AVR::S_HHI8:
|
|
Kind = isNegated() ? AVR::fixup_ms8_ldi_neg : AVR::fixup_ms8_ldi;
|
|
break;
|
|
|
|
case AVR::S_PM_LO8:
|
|
Kind = isNegated() ? AVR::fixup_lo8_ldi_pm_neg : AVR::fixup_lo8_ldi_pm;
|
|
break;
|
|
case AVR::S_PM_HI8:
|
|
Kind = isNegated() ? AVR::fixup_hi8_ldi_pm_neg : AVR::fixup_hi8_ldi_pm;
|
|
break;
|
|
case AVR::S_PM_HH8:
|
|
Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm;
|
|
break;
|
|
case AVR::S_PM:
|
|
case AVR::S_GS:
|
|
Kind = AVR::fixup_16_pm;
|
|
break;
|
|
case AVR::S_LO8_GS:
|
|
Kind = AVR::fixup_lo8_ldi_gs;
|
|
break;
|
|
case AVR::S_HI8_GS:
|
|
Kind = AVR::fixup_hi8_ldi_gs;
|
|
break;
|
|
|
|
default:
|
|
llvm_unreachable("Uninitialized expression");
|
|
}
|
|
|
|
return Kind;
|
|
}
|
|
|
|
void AVRMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
|
|
const MCSpecifierExpr &Expr) const {
|
|
auto &E = static_cast<const AVRMCExpr &>(Expr);
|
|
assert(E.getSpecifier() != AVR::S_AVR_NONE);
|
|
OS << E.getName() << '(';
|
|
if (E.isNegated())
|
|
OS << '-' << '(';
|
|
printExpr(OS, *E.getSubExpr());
|
|
if (E.isNegated())
|
|
OS << ')';
|
|
OS << ')';
|
|
}
|
|
|
|
int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const {
|
|
if (Negated)
|
|
Value *= -1;
|
|
|
|
switch (getSpecifier()) {
|
|
case AVR::S_LO8:
|
|
Value &= 0xff;
|
|
break;
|
|
case AVR::S_HI8:
|
|
Value &= 0xff00;
|
|
Value >>= 8;
|
|
break;
|
|
case AVR::S_HH8:
|
|
Value &= 0xff0000;
|
|
Value >>= 16;
|
|
break;
|
|
case AVR::S_HHI8:
|
|
Value &= 0xff000000;
|
|
Value >>= 24;
|
|
break;
|
|
case AVR::S_PM_LO8:
|
|
case AVR::S_LO8_GS:
|
|
Value >>= 1; // Program memory addresses must always be shifted by one.
|
|
Value &= 0xff;
|
|
break;
|
|
case AVR::S_PM_HI8:
|
|
case AVR::S_HI8_GS:
|
|
Value >>= 1; // Program memory addresses must always be shifted by one.
|
|
Value &= 0xff00;
|
|
Value >>= 8;
|
|
break;
|
|
case AVR::S_PM_HH8:
|
|
Value >>= 1; // Program memory addresses must always be shifted by one.
|
|
Value &= 0xff0000;
|
|
Value >>= 16;
|
|
break;
|
|
case AVR::S_PM:
|
|
case AVR::S_GS:
|
|
Value >>= 1; // Program memory addresses must always be shifted by one.
|
|
break;
|
|
|
|
case AVR::S_AVR_NONE:
|
|
default:
|
|
llvm_unreachable("Uninitialized expression.");
|
|
}
|
|
return static_cast<uint64_t>(Value) & 0xff;
|
|
}
|
|
|
|
// bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result,
|
|
// const MCAssembler *Asm) const {
|
|
bool AVRMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr,
|
|
MCValue &Result,
|
|
const MCAssembler *Asm) const {
|
|
auto &E = static_cast<const AVRMCExpr &>(Expr);
|
|
MCValue Value;
|
|
bool isRelocatable = E.getSubExpr()->evaluateAsRelocatable(Value, Asm);
|
|
if (!isRelocatable)
|
|
return false;
|
|
|
|
if (Value.isAbsolute()) {
|
|
Result = MCValue::get(E.evaluateAsInt64(Value.getConstant()));
|
|
} else {
|
|
if (!Asm || !Asm->hasLayout())
|
|
return false;
|
|
|
|
auto Spec = AVR::S_None;
|
|
if (Value.getSpecifier())
|
|
return false;
|
|
assert(!Value.getSubSym());
|
|
if (E.getSpecifier() == AVR::S_PM)
|
|
Spec = AVR::S_PM;
|
|
|
|
// TODO: don't attach specifier to MCSymbolRefExpr.
|
|
Result =
|
|
MCValue::get(Value.getAddSym(), nullptr, Value.getConstant(), Spec);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AVRMCExpr::evaluateAsConstant(int64_t &Result) const {
|
|
MCValue Value;
|
|
bool isRelocatable = getSubExpr()->evaluateAsRelocatable(Value, nullptr);
|
|
if (!isRelocatable)
|
|
return false;
|
|
|
|
if (Value.isAbsolute()) {
|
|
Result = evaluateAsInt64(Value.getConstant());
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|