You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.234
Former-commit-id: 8071ec1a8c5eaa9be24b41745add19297608001f
This commit is contained in:
parent
f32dbaf0b2
commit
212f6bafcb
@ -1,486 +0,0 @@
|
||||
//===-- AVRAsmBackend.cpp - AVR Asm Backend ------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the AVRAsmBackend class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/AVRAsmBackend.h"
|
||||
#include "MCTargetDesc/AVRFixupKinds.h"
|
||||
#include "MCTargetDesc/AVRMCTargetDesc.h"
|
||||
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
// FIXME: we should be doing checks to make sure asm operands
|
||||
// are not out of bounds.
|
||||
|
||||
namespace adjust {
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void signed_width(unsigned Width, uint64_t Value, std::string Description,
|
||||
const MCFixup &Fixup, MCContext *Ctx = nullptr) {
|
||||
if (!isIntN(Width, Value)) {
|
||||
std::string Diagnostic = "out of range " + Description;
|
||||
|
||||
int64_t Min = minIntN(Width);
|
||||
int64_t Max = maxIntN(Width);
|
||||
|
||||
Diagnostic += " (expected an integer in the range " + std::to_string(Min) +
|
||||
" to " + std::to_string(Max) + ")";
|
||||
|
||||
if (Ctx) {
|
||||
Ctx->reportFatalError(Fixup.getLoc(), Diagnostic);
|
||||
} else {
|
||||
llvm_unreachable(Diagnostic.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unsigned_width(unsigned Width, uint64_t Value, std::string Description,
|
||||
const MCFixup &Fixup, MCContext *Ctx = nullptr) {
|
||||
if (!isUIntN(Width, Value)) {
|
||||
std::string Diagnostic = "out of range " + Description;
|
||||
|
||||
int64_t Max = maxUIntN(Width);
|
||||
|
||||
Diagnostic += " (expected an integer in the range 0 to " +
|
||||
std::to_string(Max) + ")";
|
||||
|
||||
if (Ctx) {
|
||||
Ctx->reportFatalError(Fixup.getLoc(), Diagnostic);
|
||||
} else {
|
||||
llvm_unreachable(Diagnostic.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjusts the value of a branch target before fixup application.
|
||||
void adjustBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
// We have one extra bit of precision because the value is rightshifted by
|
||||
// one.
|
||||
unsigned_width(Size + 1, Value, std::string("branch target"), Fixup, Ctx);
|
||||
|
||||
// Rightshifts the value by one.
|
||||
AVR::fixups::adjustBranchTarget(Value);
|
||||
}
|
||||
|
||||
/// Adjusts the value of a relative branch target before fixup application.
|
||||
void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
// We have one extra bit of precision because the value is rightshifted by
|
||||
// one.
|
||||
signed_width(Size + 1, Value, std::string("branch target"), Fixup, Ctx);
|
||||
|
||||
Value -= 2;
|
||||
|
||||
// Rightshifts the value by one.
|
||||
AVR::fixups::adjustBranchTarget(Value);
|
||||
}
|
||||
|
||||
/// 22-bit absolute fixup.
|
||||
///
|
||||
/// Resolves to:
|
||||
/// 1001 kkkk 010k kkkk kkkk kkkk 111k kkkk
|
||||
///
|
||||
/// Offset of 0 (so the result is left shifted by 3 bits before application).
|
||||
void fixup_call(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
adjustBranch(Size, Fixup, Value, Ctx);
|
||||
|
||||
auto top = Value & (0xf00000 << 6); // the top four bits
|
||||
auto middle = Value & (0x1ffff << 5); // the middle 13 bits
|
||||
auto bottom = Value & 0x1f; // end bottom 5 bits
|
||||
|
||||
Value = (top << 6) | (middle << 3) | (bottom << 0);
|
||||
}
|
||||
|
||||
/// 7-bit PC-relative fixup.
|
||||
///
|
||||
/// Resolves to:
|
||||
/// 0000 00kk kkkk k000
|
||||
/// Offset of 0 (so the result is left shifted by 3 bits before application).
|
||||
void fixup_7_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
adjustRelativeBranch(Size, Fixup, Value, Ctx);
|
||||
|
||||
// Because the value may be negative, we must mask out the sign bits
|
||||
Value &= 0x7f;
|
||||
}
|
||||
|
||||
/// 12-bit PC-relative fixup.
|
||||
/// Yes, the fixup is 12 bits even though the name says otherwise.
|
||||
///
|
||||
/// Resolves to:
|
||||
/// 0000 kkkk kkkk kkkk
|
||||
/// Offset of 0 (so the result isn't left-shifted before application).
|
||||
void fixup_13_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
adjustRelativeBranch(Size, Fixup, Value, Ctx);
|
||||
|
||||
// Because the value may be negative, we must mask out the sign bits
|
||||
Value &= 0xfff;
|
||||
}
|
||||
|
||||
/// 6-bit fixup for the immediate operand of the ADIW family of
|
||||
/// instructions.
|
||||
///
|
||||
/// Resolves to:
|
||||
/// 0000 0000 kk00 kkkk
|
||||
void fixup_6_adiw(const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
unsigned_width(6, Value, std::string("immediate"), Fixup, Ctx);
|
||||
|
||||
Value = ((Value & 0x30) << 2) | (Value & 0x0f);
|
||||
}
|
||||
|
||||
/// 5-bit port number fixup on the SBIC family of instructions.
|
||||
///
|
||||
/// Resolves to:
|
||||
/// 0000 0000 AAAA A000
|
||||
void fixup_port5(const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
unsigned_width(5, Value, std::string("port number"), Fixup, Ctx);
|
||||
|
||||
Value &= 0x1f;
|
||||
|
||||
Value <<= 3;
|
||||
}
|
||||
|
||||
/// 6-bit port number fixup on the `IN` family of instructions.
|
||||
///
|
||||
/// Resolves to:
|
||||
/// 1011 0AAd dddd AAAA
|
||||
void fixup_port6(const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
unsigned_width(6, Value, std::string("port number"), Fixup, Ctx);
|
||||
|
||||
Value = ((Value & 0x30) << 5) | (Value & 0x0f);
|
||||
}
|
||||
|
||||
/// Adjusts a program memory address.
|
||||
/// This is a simple right-shift.
|
||||
void pm(uint64_t &Value) {
|
||||
Value >>= 1;
|
||||
}
|
||||
|
||||
/// Fixups relating to the LDI instruction.
|
||||
namespace ldi {
|
||||
|
||||
/// Adjusts a value to fix up the immediate of an `LDI Rd, K` instruction.
|
||||
///
|
||||
/// Resolves to:
|
||||
/// 0000 KKKK 0000 KKKK
|
||||
/// Offset of 0 (so the result isn't left-shifted before application).
|
||||
void fixup(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
uint64_t upper = Value & 0xf0;
|
||||
uint64_t lower = Value & 0x0f;
|
||||
|
||||
Value = (upper << 4) | lower;
|
||||
}
|
||||
|
||||
void neg(uint64_t &Value) { Value *= -1; }
|
||||
|
||||
void lo8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
Value &= 0xff;
|
||||
ldi::fixup(Size, Fixup, Value, Ctx);
|
||||
}
|
||||
|
||||
void hi8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
Value = (Value & 0xff00) >> 8;
|
||||
ldi::fixup(Size, Fixup, Value, Ctx);
|
||||
}
|
||||
|
||||
void hh8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
Value = (Value & 0xff0000) >> 16;
|
||||
ldi::fixup(Size, Fixup, Value, Ctx);
|
||||
}
|
||||
|
||||
void ms8(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
|
||||
MCContext *Ctx = nullptr) {
|
||||
Value = (Value & 0xff000000) >> 24;
|
||||
ldi::fixup(Size, Fixup, Value, Ctx);
|
||||
}
|
||||
|
||||
} // end of ldi namespace
|
||||
} // end of adjust namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// Prepare value for the target space for it
|
||||
void AVRAsmBackend::adjustFixupValue(const MCFixup &Fixup,
|
||||
const MCValue &Target,
|
||||
uint64_t &Value,
|
||||
MCContext *Ctx) const {
|
||||
// The size of the fixup in bits.
|
||||
uint64_t Size = AVRAsmBackend::getFixupKindInfo(Fixup.getKind()).TargetSize;
|
||||
|
||||
unsigned Kind = Fixup.getKind();
|
||||
|
||||
// Parsed LLVM-generated temporary labels are already
|
||||
// adjusted for instruction size, but normal labels aren't.
|
||||
//
|
||||
// To handle both cases, we simply un-adjust the temporary label
|
||||
// case so it acts like all other labels.
|
||||
if (const MCSymbolRefExpr *A = Target.getSymA()) {
|
||||
if (A->getSymbol().isTemporary())
|
||||
Value += 2;
|
||||
}
|
||||
|
||||
switch (Kind) {
|
||||
default:
|
||||
llvm_unreachable("unhandled fixup");
|
||||
case AVR::fixup_7_pcrel:
|
||||
adjust::fixup_7_pcrel(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_13_pcrel:
|
||||
adjust::fixup_13_pcrel(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_call:
|
||||
adjust::fixup_call(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_ldi:
|
||||
adjust::ldi::fixup(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_lo8_ldi:
|
||||
adjust::ldi::lo8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_lo8_ldi_pm:
|
||||
case AVR::fixup_lo8_ldi_gs:
|
||||
adjust::pm(Value);
|
||||
adjust::ldi::lo8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_hi8_ldi:
|
||||
adjust::ldi::hi8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_hi8_ldi_pm:
|
||||
case AVR::fixup_hi8_ldi_gs:
|
||||
adjust::pm(Value);
|
||||
adjust::ldi::hi8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_hh8_ldi:
|
||||
case AVR::fixup_hh8_ldi_pm:
|
||||
if (Kind == AVR::fixup_hh8_ldi_pm) adjust::pm(Value);
|
||||
|
||||
adjust::ldi::hh8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_ms8_ldi:
|
||||
adjust::ldi::ms8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
|
||||
case AVR::fixup_lo8_ldi_neg:
|
||||
case AVR::fixup_lo8_ldi_pm_neg:
|
||||
if (Kind == AVR::fixup_lo8_ldi_pm_neg) adjust::pm(Value);
|
||||
|
||||
adjust::ldi::neg(Value);
|
||||
adjust::ldi::lo8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_hi8_ldi_neg:
|
||||
case AVR::fixup_hi8_ldi_pm_neg:
|
||||
if (Kind == AVR::fixup_hi8_ldi_pm_neg) adjust::pm(Value);
|
||||
|
||||
adjust::ldi::neg(Value);
|
||||
adjust::ldi::hi8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_hh8_ldi_neg:
|
||||
case AVR::fixup_hh8_ldi_pm_neg:
|
||||
if (Kind == AVR::fixup_hh8_ldi_pm_neg) adjust::pm(Value);
|
||||
|
||||
adjust::ldi::neg(Value);
|
||||
adjust::ldi::hh8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_ms8_ldi_neg:
|
||||
adjust::ldi::neg(Value);
|
||||
adjust::ldi::ms8(Size, Fixup, Value, Ctx);
|
||||
break;
|
||||
case AVR::fixup_16:
|
||||
adjust::unsigned_width(16, Value, std::string("port number"), Fixup, Ctx);
|
||||
|
||||
Value &= 0xffff;
|
||||
break;
|
||||
case AVR::fixup_16_pm:
|
||||
Value >>= 1; // Flash addresses are always shifted.
|
||||
adjust::unsigned_width(16, Value, std::string("port number"), Fixup, Ctx);
|
||||
|
||||
Value &= 0xffff;
|
||||
break;
|
||||
|
||||
case AVR::fixup_6_adiw:
|
||||
adjust::fixup_6_adiw(Fixup, Value, Ctx);
|
||||
break;
|
||||
|
||||
case AVR::fixup_port5:
|
||||
adjust::fixup_port5(Fixup, Value, Ctx);
|
||||
break;
|
||||
|
||||
case AVR::fixup_port6:
|
||||
adjust::fixup_port6(Fixup, Value, Ctx);
|
||||
break;
|
||||
|
||||
// Fixups which do not require adjustments.
|
||||
case FK_Data_1:
|
||||
case FK_Data_2:
|
||||
case FK_Data_4:
|
||||
case FK_Data_8:
|
||||
break;
|
||||
|
||||
case FK_GPRel_4:
|
||||
llvm_unreachable("don't know how to adjust this fixup");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
AVRAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
|
||||
return createAVRELFObjectWriter(OS,
|
||||
MCELFObjectTargetWriter::getOSABI(OSType));
|
||||
}
|
||||
|
||||
void AVRAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsPCRel) const {
|
||||
adjustFixupValue(Fixup, Target, Value, &Asm.getContext());
|
||||
if (Value == 0)
|
||||
return; // Doesn't change encoding.
|
||||
|
||||
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
|
||||
|
||||
// The number of bits in the fixup mask
|
||||
auto NumBits = Info.TargetSize + Info.TargetOffset;
|
||||
auto NumBytes = (NumBits / 8) + ((NumBits % 8) == 0 ? 0 : 1);
|
||||
|
||||
// Shift the value into position.
|
||||
Value <<= Info.TargetOffset;
|
||||
|
||||
unsigned Offset = Fixup.getOffset();
|
||||
assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
|
||||
|
||||
// For each byte of the fragment that the fixup touches, mask in the
|
||||
// bits from the fixup value.
|
||||
for (unsigned i = 0; i < NumBytes; ++i) {
|
||||
uint8_t mask = (((Value >> (i * 8)) & 0xff));
|
||||
Data[Offset + i] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
MCFixupKindInfo const &AVRAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
||||
// NOTE: Many AVR fixups work on sets of non-contignous bits. We work around
|
||||
// this by saying that the fixup is the size of the entire instruction.
|
||||
const static MCFixupKindInfo Infos[AVR::NumTargetFixupKinds] = {
|
||||
// This table *must* be in same the order of fixup_* kinds in
|
||||
// AVRFixupKinds.h.
|
||||
//
|
||||
// name offset bits flags
|
||||
{"fixup_32", 0, 32, 0},
|
||||
|
||||
{"fixup_7_pcrel", 3, 7, MCFixupKindInfo::FKF_IsPCRel},
|
||||
{"fixup_13_pcrel", 0, 12, MCFixupKindInfo::FKF_IsPCRel},
|
||||
|
||||
{"fixup_16", 0, 16, 0},
|
||||
{"fixup_16_pm", 0, 16, 0},
|
||||
|
||||
{"fixup_ldi", 0, 8, 0},
|
||||
|
||||
{"fixup_lo8_ldi", 0, 8, 0},
|
||||
{"fixup_hi8_ldi", 0, 8, 0},
|
||||
{"fixup_hh8_ldi", 0, 8, 0},
|
||||
{"fixup_ms8_ldi", 0, 8, 0},
|
||||
|
||||
{"fixup_lo8_ldi_neg", 0, 8, 0},
|
||||
{"fixup_hi8_ldi_neg", 0, 8, 0},
|
||||
{"fixup_hh8_ldi_neg", 0, 8, 0},
|
||||
{"fixup_ms8_ldi_neg", 0, 8, 0},
|
||||
|
||||
{"fixup_lo8_ldi_pm", 0, 8, 0},
|
||||
{"fixup_hi8_ldi_pm", 0, 8, 0},
|
||||
{"fixup_hh8_ldi_pm", 0, 8, 0},
|
||||
|
||||
{"fixup_lo8_ldi_pm_neg", 0, 8, 0},
|
||||
{"fixup_hi8_ldi_pm_neg", 0, 8, 0},
|
||||
{"fixup_hh8_ldi_pm_neg", 0, 8, 0},
|
||||
|
||||
{"fixup_call", 0, 22, 0},
|
||||
|
||||
{"fixup_6", 0, 16, 0}, // non-contiguous
|
||||
{"fixup_6_adiw", 0, 6, 0},
|
||||
|
||||
{"fixup_lo8_ldi_gs", 0, 8, 0},
|
||||
{"fixup_hi8_ldi_gs", 0, 8, 0},
|
||||
|
||||
{"fixup_8", 0, 8, 0},
|
||||
{"fixup_8_lo8", 0, 8, 0},
|
||||
{"fixup_8_hi8", 0, 8, 0},
|
||||
{"fixup_8_hlo8", 0, 8, 0},
|
||||
|
||||
{"fixup_diff8", 0, 8, 0},
|
||||
{"fixup_diff16", 0, 16, 0},
|
||||
{"fixup_diff32", 0, 32, 0},
|
||||
|
||||
{"fixup_lds_sts_16", 0, 16, 0},
|
||||
|
||||
{"fixup_port6", 0, 16, 0}, // non-contiguous
|
||||
{"fixup_port5", 3, 5, 0},
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
|
||||
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
|
||||
"Invalid kind!");
|
||||
|
||||
return Infos[Kind - FirstTargetFixupKind];
|
||||
}
|
||||
|
||||
bool AVRAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
|
||||
// If the count is not 2-byte aligned, we must be writing data into the text
|
||||
// section (otherwise we have unaligned instructions, and thus have far
|
||||
// bigger problems), so just write zeros instead.
|
||||
assert((Count % 2) == 0 && "NOP instructions must be 2 bytes");
|
||||
|
||||
OW->WriteZeros(Count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AVRAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
|
||||
const MCFixup &Fixup,
|
||||
const MCValue &Target) {
|
||||
switch ((unsigned) Fixup.getKind()) {
|
||||
default: return false;
|
||||
// Fixups which should always be recorded as relocations.
|
||||
case AVR::fixup_7_pcrel:
|
||||
case AVR::fixup_13_pcrel:
|
||||
case AVR::fixup_call:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
MCAsmBackend *createAVRAsmBackend(const Target &T, const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const llvm::MCTargetOptions &TO) {
|
||||
return new AVRAsmBackend(STI.getTargetTriple().getOS());
|
||||
}
|
||||
|
||||
} // end of namespace llvm
|
||||
|
@ -1,77 +0,0 @@
|
||||
//===-- AVRAsmBackend.h - AVR Asm Backend --------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// \file The AVR assembly backend implementation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
#ifndef LLVM_AVR_ASM_BACKEND_H
|
||||
#define LLVM_AVR_ASM_BACKEND_H
|
||||
|
||||
#include "MCTargetDesc/AVRFixupKinds.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCAssembler;
|
||||
class MCObjectWriter;
|
||||
class Target;
|
||||
|
||||
struct MCFixupKindInfo;
|
||||
|
||||
/// Utilities for manipulating generated AVR machine code.
|
||||
class AVRAsmBackend : public MCAsmBackend {
|
||||
public:
|
||||
|
||||
AVRAsmBackend(Triple::OSType OSType)
|
||||
: MCAsmBackend(), OSType(OSType) {}
|
||||
|
||||
void adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
|
||||
uint64_t &Value, MCContext *Ctx = nullptr) const;
|
||||
|
||||
std::unique_ptr<MCObjectWriter> createObjectWriter(raw_pwrite_stream &OS) const override;
|
||||
|
||||
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsPCRel) const override;
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
|
||||
|
||||
unsigned getNumFixupKinds() const override {
|
||||
return AVR::NumTargetFixupKinds;
|
||||
}
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
|
||||
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override {
|
||||
llvm_unreachable("RelaxInstruction() unimplemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {}
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
|
||||
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target) override;
|
||||
|
||||
private:
|
||||
Triple::OSType OSType;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_AVR_ASM_BACKEND_H
|
||||
|
@ -1,162 +0,0 @@
|
||||
//===-- AVRELFObjectWriter.cpp - AVR ELF Writer ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/AVRFixupKinds.h"
|
||||
#include "MCTargetDesc/AVRMCTargetDesc.h"
|
||||
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Writes AVR machine code into an ELF32 object file.
|
||||
class AVRELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
AVRELFObjectWriter(uint8_t OSABI);
|
||||
|
||||
virtual ~AVRELFObjectWriter() {}
|
||||
|
||||
unsigned getRelocType(MCContext &Ctx,
|
||||
const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const override;
|
||||
};
|
||||
|
||||
AVRELFObjectWriter::AVRELFObjectWriter(uint8_t OSABI)
|
||||
: MCELFObjectTargetWriter(false, OSABI, ELF::EM_AVR, true) {}
|
||||
|
||||
unsigned AVRELFObjectWriter::getRelocType(MCContext &Ctx,
|
||||
const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
|
||||
switch ((unsigned) Fixup.getKind()) {
|
||||
case FK_Data_1:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_AVR_8;
|
||||
case MCSymbolRefExpr::VK_AVR_DIFF8:
|
||||
return ELF::R_AVR_DIFF8;
|
||||
case MCSymbolRefExpr::VK_AVR_LO8:
|
||||
return ELF::R_AVR_8_LO8;
|
||||
case MCSymbolRefExpr::VK_AVR_HI8:
|
||||
return ELF::R_AVR_8_HI8;
|
||||
case MCSymbolRefExpr::VK_AVR_HLO8:
|
||||
return ELF::R_AVR_8_HLO8;
|
||||
}
|
||||
case FK_Data_4:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_AVR_32;
|
||||
case MCSymbolRefExpr::VK_AVR_DIFF32:
|
||||
return ELF::R_AVR_DIFF32;
|
||||
}
|
||||
case FK_Data_2:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_AVR_16;
|
||||
case MCSymbolRefExpr::VK_AVR_NONE:
|
||||
return ELF::R_AVR_16_PM;
|
||||
case MCSymbolRefExpr::VK_AVR_DIFF16:
|
||||
return ELF::R_AVR_DIFF16;
|
||||
}
|
||||
case AVR::fixup_32:
|
||||
return ELF::R_AVR_32;
|
||||
case AVR::fixup_7_pcrel:
|
||||
return ELF::R_AVR_7_PCREL;
|
||||
case AVR::fixup_13_pcrel:
|
||||
return ELF::R_AVR_13_PCREL;
|
||||
case AVR::fixup_16:
|
||||
return ELF::R_AVR_16;
|
||||
case AVR::fixup_16_pm:
|
||||
return ELF::R_AVR_16_PM;
|
||||
case AVR::fixup_lo8_ldi:
|
||||
return ELF::R_AVR_LO8_LDI;
|
||||
case AVR::fixup_hi8_ldi:
|
||||
return ELF::R_AVR_HI8_LDI;
|
||||
case AVR::fixup_hh8_ldi:
|
||||
return ELF::R_AVR_HH8_LDI;
|
||||
case AVR::fixup_lo8_ldi_neg:
|
||||
return ELF::R_AVR_LO8_LDI_NEG;
|
||||
case AVR::fixup_hi8_ldi_neg:
|
||||
return ELF::R_AVR_HI8_LDI_NEG;
|
||||
case AVR::fixup_hh8_ldi_neg:
|
||||
return ELF::R_AVR_HH8_LDI_NEG;
|
||||
case AVR::fixup_lo8_ldi_pm:
|
||||
return ELF::R_AVR_LO8_LDI_PM;
|
||||
case AVR::fixup_hi8_ldi_pm:
|
||||
return ELF::R_AVR_HI8_LDI_PM;
|
||||
case AVR::fixup_hh8_ldi_pm:
|
||||
return ELF::R_AVR_HH8_LDI_PM;
|
||||
case AVR::fixup_lo8_ldi_pm_neg:
|
||||
return ELF::R_AVR_LO8_LDI_PM_NEG;
|
||||
case AVR::fixup_hi8_ldi_pm_neg:
|
||||
return ELF::R_AVR_HI8_LDI_PM_NEG;
|
||||
case AVR::fixup_hh8_ldi_pm_neg:
|
||||
return ELF::R_AVR_HH8_LDI_PM_NEG;
|
||||
case AVR::fixup_call:
|
||||
return ELF::R_AVR_CALL;
|
||||
case AVR::fixup_ldi:
|
||||
return ELF::R_AVR_LDI;
|
||||
case AVR::fixup_6:
|
||||
return ELF::R_AVR_6;
|
||||
case AVR::fixup_6_adiw:
|
||||
return ELF::R_AVR_6_ADIW;
|
||||
case AVR::fixup_ms8_ldi:
|
||||
return ELF::R_AVR_MS8_LDI;
|
||||
case AVR::fixup_ms8_ldi_neg:
|
||||
return ELF::R_AVR_MS8_LDI_NEG;
|
||||
case AVR::fixup_lo8_ldi_gs:
|
||||
return ELF::R_AVR_LO8_LDI_GS;
|
||||
case AVR::fixup_hi8_ldi_gs:
|
||||
return ELF::R_AVR_HI8_LDI_GS;
|
||||
case AVR::fixup_8:
|
||||
return ELF::R_AVR_8;
|
||||
case AVR::fixup_8_lo8:
|
||||
return ELF::R_AVR_8_LO8;
|
||||
case AVR::fixup_8_hi8:
|
||||
return ELF::R_AVR_8_HI8;
|
||||
case AVR::fixup_8_hlo8:
|
||||
return ELF::R_AVR_8_HLO8;
|
||||
case AVR::fixup_diff8:
|
||||
return ELF::R_AVR_DIFF8;
|
||||
case AVR::fixup_diff16:
|
||||
return ELF::R_AVR_DIFF16;
|
||||
case AVR::fixup_diff32:
|
||||
return ELF::R_AVR_DIFF32;
|
||||
case AVR::fixup_lds_sts_16:
|
||||
return ELF::R_AVR_LDS_STS_16;
|
||||
case AVR::fixup_port6:
|
||||
return ELF::R_AVR_PORT6;
|
||||
case AVR::fixup_port5:
|
||||
return ELF::R_AVR_PORT5;
|
||||
default:
|
||||
llvm_unreachable("invalid fixup kind!");
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createAVRELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI) {
|
||||
std::unique_ptr<MCELFObjectTargetWriter> MOTW(new AVRELFObjectWriter(OSABI));
|
||||
return createELFObjectWriter(std::move(MOTW), OS, true);
|
||||
}
|
||||
|
||||
} // end of namespace llvm
|
||||
|
@ -1,68 +0,0 @@
|
||||
#include "AVRELFStreamer.h"
|
||||
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/SubtargetFeature.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
|
||||
#include "AVRMCTargetDesc.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
static unsigned getEFlagsForFeatureSet(const FeatureBitset &Features) {
|
||||
unsigned EFlags = 0;
|
||||
|
||||
// Set architecture
|
||||
if (Features[AVR::ELFArchAVR1])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR1;
|
||||
else if (Features[AVR::ELFArchAVR2])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR2;
|
||||
else if (Features[AVR::ELFArchAVR25])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR25;
|
||||
else if (Features[AVR::ELFArchAVR3])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR3;
|
||||
else if (Features[AVR::ELFArchAVR31])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR31;
|
||||
else if (Features[AVR::ELFArchAVR35])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR35;
|
||||
else if (Features[AVR::ELFArchAVR4])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR4;
|
||||
else if (Features[AVR::ELFArchAVR5])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR5;
|
||||
else if (Features[AVR::ELFArchAVR51])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR51;
|
||||
else if (Features[AVR::ELFArchAVR6])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVR6;
|
||||
else if (Features[AVR::ELFArchTiny])
|
||||
EFlags |= ELF::EF_AVR_ARCH_AVRTINY;
|
||||
else if (Features[AVR::ELFArchXMEGA1])
|
||||
EFlags |= ELF::EF_AVR_ARCH_XMEGA1;
|
||||
else if (Features[AVR::ELFArchXMEGA2])
|
||||
EFlags |= ELF::EF_AVR_ARCH_XMEGA2;
|
||||
else if (Features[AVR::ELFArchXMEGA3])
|
||||
EFlags |= ELF::EF_AVR_ARCH_XMEGA3;
|
||||
else if (Features[AVR::ELFArchXMEGA4])
|
||||
EFlags |= ELF::EF_AVR_ARCH_XMEGA4;
|
||||
else if (Features[AVR::ELFArchXMEGA5])
|
||||
EFlags |= ELF::EF_AVR_ARCH_XMEGA5;
|
||||
else if (Features[AVR::ELFArchXMEGA6])
|
||||
EFlags |= ELF::EF_AVR_ARCH_XMEGA6;
|
||||
else if (Features[AVR::ELFArchXMEGA7])
|
||||
EFlags |= ELF::EF_AVR_ARCH_XMEGA7;
|
||||
|
||||
return EFlags;
|
||||
}
|
||||
|
||||
AVRELFStreamer::AVRELFStreamer(MCStreamer &S,
|
||||
const MCSubtargetInfo &STI)
|
||||
: AVRTargetStreamer(S) {
|
||||
|
||||
MCAssembler &MCA = getStreamer().getAssembler();
|
||||
unsigned EFlags = MCA.getELFHeaderEFlags();
|
||||
|
||||
EFlags |= getEFlagsForFeatureSet(STI.getFeatureBits());
|
||||
|
||||
MCA.setELFHeaderEFlags(EFlags);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
@ -1,29 +0,0 @@
|
||||
//===----- AVRELFStreamer.h - AVR Target Streamer --------------*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_AVR_ELF_STREAMER_H
|
||||
#define LLVM_AVR_ELF_STREAMER_H
|
||||
|
||||
#include "AVRTargetStreamer.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// A target streamer for an AVR ELF object file.
|
||||
class AVRELFStreamer : public AVRTargetStreamer {
|
||||
public:
|
||||
AVRELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
|
||||
|
||||
MCELFStreamer &getStreamer() {
|
||||
return static_cast<MCELFStreamer &>(Streamer);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -1,148 +0,0 @@
|
||||
//===-- AVRFixupKinds.h - AVR Specific Fixup Entries ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_AVR_FIXUP_KINDS_H
|
||||
#define LLVM_AVR_FIXUP_KINDS_H
|
||||
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace AVR {
|
||||
|
||||
/// The set of supported fixups.
|
||||
///
|
||||
/// Although most of the current fixup types reflect a unique relocation
|
||||
/// one can have multiple fixup types for a given relocation and thus need
|
||||
/// to be uniquely named.
|
||||
///
|
||||
/// \note This table *must* be in the same order of
|
||||
/// MCFixupKindInfo Infos[AVR::NumTargetFixupKinds]
|
||||
/// in `AVRAsmBackend.cpp`.
|
||||
enum Fixups {
|
||||
/// A 32-bit AVR fixup.
|
||||
fixup_32 = FirstTargetFixupKind,
|
||||
|
||||
/// A 7-bit PC-relative fixup for the family of conditional
|
||||
/// branches which take 7-bit targets (BRNE,BRGT,etc).
|
||||
fixup_7_pcrel,
|
||||
/// A 12-bit PC-relative fixup for the family of branches
|
||||
/// which take 12-bit targets (RJMP,RCALL,etc).
|
||||
/// \note Although the fixup is labelled as 13 bits, it
|
||||
/// is actually only encoded in 12. The reason for
|
||||
/// The nonmenclature is that AVR branch targets are
|
||||
/// rightshifted by 1, because instructions are always
|
||||
/// aligned to 2 bytes, so the 0'th bit is always 0.
|
||||
/// This way there is 13-bits of precision.
|
||||
fixup_13_pcrel,
|
||||
|
||||
/// A 16-bit address.
|
||||
fixup_16,
|
||||
/// A 16-bit program memory address.
|
||||
fixup_16_pm,
|
||||
|
||||
/// Replaces the 8-bit immediate with another value.
|
||||
fixup_ldi,
|
||||
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the lower 8 bits of a 16-bit value (bits 0-7).
|
||||
fixup_lo8_ldi,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a 16-bit value (bits 8-15).
|
||||
fixup_hi8_ldi,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a 24-bit value (bits 16-23).
|
||||
fixup_hh8_ldi,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a 32-bit value (bits 24-31).
|
||||
fixup_ms8_ldi,
|
||||
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the lower 8 bits of a negated 16-bit value (bits 0-7).
|
||||
fixup_lo8_ldi_neg,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a negated 16-bit value (bits 8-15).
|
||||
fixup_hi8_ldi_neg,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a negated negated 24-bit value (bits 16-23).
|
||||
fixup_hh8_ldi_neg,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a negated negated 32-bit value (bits 24-31).
|
||||
fixup_ms8_ldi_neg,
|
||||
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the lower 8 bits of a 16-bit program memory address value (bits 0-7).
|
||||
fixup_lo8_ldi_pm,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a 16-bit program memory address value (bits
|
||||
/// 8-15).
|
||||
fixup_hi8_ldi_pm,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a 24-bit program memory address value (bits
|
||||
/// 16-23).
|
||||
fixup_hh8_ldi_pm,
|
||||
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the lower 8 bits of a negated 16-bit program memory address value
|
||||
/// (bits 0-7).
|
||||
fixup_lo8_ldi_pm_neg,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a negated 16-bit program memory address value
|
||||
/// (bits 8-15).
|
||||
fixup_hi8_ldi_pm_neg,
|
||||
/// Replaces the immediate operand of a 16-bit `Rd, K` instruction
|
||||
/// with the upper 8 bits of a negated 24-bit program memory address value
|
||||
/// (bits 16-23).
|
||||
fixup_hh8_ldi_pm_neg,
|
||||
|
||||
/// A 22-bit fixup for the target of a `CALL k` or `JMP k` instruction.
|
||||
fixup_call,
|
||||
|
||||
fixup_6,
|
||||
/// A symbol+addr fixup for the `LDD <x>+<n>, <r>" family of instructions.
|
||||
fixup_6_adiw,
|
||||
|
||||
fixup_lo8_ldi_gs,
|
||||
fixup_hi8_ldi_gs,
|
||||
|
||||
fixup_8,
|
||||
fixup_8_lo8,
|
||||
fixup_8_hi8,
|
||||
fixup_8_hlo8,
|
||||
|
||||
fixup_diff8,
|
||||
fixup_diff16,
|
||||
fixup_diff32,
|
||||
|
||||
fixup_lds_sts_16,
|
||||
|
||||
/// A 6-bit port address.
|
||||
fixup_port6,
|
||||
/// A 5-bit port address.
|
||||
fixup_port5,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
};
|
||||
|
||||
namespace fixups {
|
||||
|
||||
/// Adjusts the value of a branch target.
|
||||
/// All branch targets in AVR are rightshifted by 1 to take advantage
|
||||
/// of the fact that all instructions are aligned to addresses of size
|
||||
/// 2, so bit 0 of an address is always 0. This gives us another bit
|
||||
/// of precision.
|
||||
/// \param[in,out] The target to adjust.
|
||||
template <typename T> inline void adjustBranchTarget(T &val) { val >>= 1; }
|
||||
|
||||
} // end of namespace fixups
|
||||
}
|
||||
} // end of namespace llvm::AVR
|
||||
|
||||
#endif // LLVM_AVR_FIXUP_KINDS_H
|
@ -1,29 +0,0 @@
|
||||
//===-- AVRMCAsmInfo.cpp - AVR asm properties -----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declarations of the AVRMCAsmInfo properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AVRMCAsmInfo.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
AVRMCAsmInfo::AVRMCAsmInfo(const Triple &TT) {
|
||||
CodePointerSize = 2;
|
||||
CalleeSaveStackSlotSize = 2;
|
||||
CommentString = ";";
|
||||
PrivateGlobalPrefix = ".L";
|
||||
UsesELFSectionDirectiveForBSS = true;
|
||||
UseIntegratedAssembler = true;
|
||||
}
|
||||
|
||||
} // end of namespace llvm
|
@ -1,31 +0,0 @@
|
||||
//===-- AVRMCAsmInfo.h - AVR asm properties ---------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the AVRMCAsmInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_AVR_ASM_INFO_H
|
||||
#define LLVM_AVR_ASM_INFO_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Triple;
|
||||
|
||||
/// Specifies the format of AVR assembly files.
|
||||
class AVRMCAsmInfo : public MCAsmInfo {
|
||||
public:
|
||||
explicit AVRMCAsmInfo(const Triple &TT);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_AVR_ASM_INFO_H
|
@ -1,305 +0,0 @@
|
||||
//===-- AVRMCCodeEmitter.cpp - Convert AVR Code to Machine Code -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the AVRMCCodeEmitter class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AVRMCCodeEmitter.h"
|
||||
|
||||
#include "MCTargetDesc/AVRMCExpr.h"
|
||||
#include "MCTargetDesc/AVRMCTargetDesc.h"
|
||||
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#define DEBUG_TYPE "mccodeemitter"
|
||||
|
||||
#define GET_INSTRMAP_INFO
|
||||
#include "AVRGenInstrInfo.inc"
|
||||
#undef GET_INSTRMAP_INFO
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Performs a post-encoding step on a `LD` or `ST` instruction.
|
||||
///
|
||||
/// The encoding of the LD/ST family of instructions is inconsistent w.r.t
|
||||
/// the pointer register and the addressing mode.
|
||||
///
|
||||
/// The permutations of the format are as followed:
|
||||
/// ld Rd, X `1001 000d dddd 1100`
|
||||
/// ld Rd, X+ `1001 000d dddd 1101`
|
||||
/// ld Rd, -X `1001 000d dddd 1110`
|
||||
///
|
||||
/// ld Rd, Y `1000 000d dddd 1000`
|
||||
/// ld Rd, Y+ `1001 000d dddd 1001`
|
||||
/// ld Rd, -Y `1001 000d dddd 1010`
|
||||
///
|
||||
/// ld Rd, Z `1000 000d dddd 0000`
|
||||
/// ld Rd, Z+ `1001 000d dddd 0001`
|
||||
/// ld Rd, -Z `1001 000d dddd 0010`
|
||||
/// ^
|
||||
/// |
|
||||
/// Note this one inconsistent bit - it is 1 sometimes and 0 at other times.
|
||||
/// There is no logical pattern. Looking at a truth table, the following
|
||||
/// formula can be derived to fit the pattern:
|
||||
//
|
||||
/// ```
|
||||
/// inconsistent_bit = is_predec OR is_postinc OR is_reg_x
|
||||
/// ```
|
||||
//
|
||||
/// We manually set this bit in this post encoder method.
|
||||
unsigned
|
||||
AVRMCCodeEmitter::loadStorePostEncoder(const MCInst &MI, unsigned EncodedValue,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
|
||||
assert(MI.getOperand(0).isReg() && MI.getOperand(1).isReg() &&
|
||||
"the load/store operands must be registers");
|
||||
|
||||
unsigned Opcode = MI.getOpcode();
|
||||
|
||||
// check whether either of the registers are the X pointer register.
|
||||
bool IsRegX = MI.getOperand(0).getReg() == AVR::R27R26 ||
|
||||
MI.getOperand(1).getReg() == AVR::R27R26;
|
||||
|
||||
bool IsPredec = Opcode == AVR::LDRdPtrPd || Opcode == AVR::STPtrPdRr;
|
||||
bool IsPostinc = Opcode == AVR::LDRdPtrPi || Opcode == AVR::STPtrPiRr;
|
||||
|
||||
// Check if we need to set the inconsistent bit
|
||||
if (IsRegX || IsPredec || IsPostinc) {
|
||||
EncodedValue |= (1 << 12);
|
||||
}
|
||||
|
||||
return EncodedValue;
|
||||
}
|
||||
|
||||
template <AVR::Fixups Fixup>
|
||||
unsigned
|
||||
AVRMCCodeEmitter::encodeRelCondBrTarget(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
|
||||
if (MO.isExpr()) {
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
||||
MCFixupKind(Fixup), MI.getLoc()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(MO.isImm());
|
||||
|
||||
// Take the size of the current instruction away.
|
||||
// With labels, this is implicitly done.
|
||||
auto target = MO.getImm();
|
||||
AVR::fixups::adjustBranchTarget(target);
|
||||
return target;
|
||||
}
|
||||
|
||||
unsigned AVRMCCodeEmitter::encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
auto MO = MI.getOperand(OpNo);
|
||||
|
||||
// The operand should be a pointer register.
|
||||
assert(MO.isReg());
|
||||
|
||||
switch (MO.getReg()) {
|
||||
case AVR::R27R26: return 0x03; // X: 0b11
|
||||
case AVR::R29R28: return 0x02; // Y: 0b10
|
||||
case AVR::R31R30: return 0x00; // Z: 0b00
|
||||
default:
|
||||
llvm_unreachable("invalid pointer register");
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes a `memri` operand.
|
||||
/// The operand is 7-bits.
|
||||
/// * The lower 6 bits is the immediate
|
||||
/// * The upper bit is the pointer register bit (Z=0,Y=1)
|
||||
unsigned AVRMCCodeEmitter::encodeMemri(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
auto RegOp = MI.getOperand(OpNo);
|
||||
auto OffsetOp = MI.getOperand(OpNo + 1);
|
||||
|
||||
assert(RegOp.isReg() && "Expected register operand");
|
||||
|
||||
uint8_t RegBit = 0;
|
||||
|
||||
switch (RegOp.getReg()) {
|
||||
default:
|
||||
llvm_unreachable("Expected either Y or Z register");
|
||||
case AVR::R31R30:
|
||||
RegBit = 0;
|
||||
break; // Z register
|
||||
case AVR::R29R28:
|
||||
RegBit = 1;
|
||||
break; // Y register
|
||||
}
|
||||
|
||||
int8_t OffsetBits;
|
||||
|
||||
if (OffsetOp.isImm()) {
|
||||
OffsetBits = OffsetOp.getImm();
|
||||
} else if (OffsetOp.isExpr()) {
|
||||
OffsetBits = 0;
|
||||
Fixups.push_back(MCFixup::create(0, OffsetOp.getExpr(),
|
||||
MCFixupKind(AVR::fixup_6), MI.getLoc()));
|
||||
} else {
|
||||
llvm_unreachable("invalid value for offset");
|
||||
}
|
||||
|
||||
return (RegBit << 6) | OffsetBits;
|
||||
}
|
||||
|
||||
unsigned AVRMCCodeEmitter::encodeComplement(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
// The operand should be an immediate.
|
||||
assert(MI.getOperand(OpNo).isImm());
|
||||
|
||||
auto Imm = MI.getOperand(OpNo).getImm();
|
||||
return (~0) - Imm;
|
||||
}
|
||||
|
||||
template <AVR::Fixups Fixup, unsigned Offset>
|
||||
unsigned AVRMCCodeEmitter::encodeImm(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
auto MO = MI.getOperand(OpNo);
|
||||
|
||||
if (MO.isExpr()) {
|
||||
if (isa<AVRMCExpr>(MO.getExpr())) {
|
||||
// If the expression is already an AVRMCExpr (i.e. a lo8(symbol),
|
||||
// we shouldn't perform any more fixups. Without this check, we would
|
||||
// instead create a fixup to the symbol named 'lo8(symbol)' which
|
||||
// is not correct.
|
||||
return getExprOpValue(MO.getExpr(), Fixups, STI);
|
||||
}
|
||||
|
||||
MCFixupKind FixupKind = static_cast<MCFixupKind>(Fixup);
|
||||
Fixups.push_back(MCFixup::create(Offset, MO.getExpr(), FixupKind, MI.getLoc()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(MO.isImm());
|
||||
return MO.getImm();
|
||||
}
|
||||
|
||||
unsigned AVRMCCodeEmitter::encodeCallTarget(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
auto MO = MI.getOperand(OpNo);
|
||||
|
||||
if (MO.isExpr()) {
|
||||
MCFixupKind FixupKind = static_cast<MCFixupKind>(AVR::fixup_call);
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(), FixupKind, MI.getLoc()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(MO.isImm());
|
||||
|
||||
auto Target = MO.getImm();
|
||||
AVR::fixups::adjustBranchTarget(Target);
|
||||
return Target;
|
||||
}
|
||||
|
||||
unsigned AVRMCCodeEmitter::getExprOpValue(const MCExpr *Expr,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
|
||||
MCExpr::ExprKind Kind = Expr->getKind();
|
||||
|
||||
if (Kind == MCExpr::Binary) {
|
||||
Expr = static_cast<const MCBinaryExpr *>(Expr)->getLHS();
|
||||
Kind = Expr->getKind();
|
||||
}
|
||||
|
||||
if (Kind == MCExpr::Target) {
|
||||
AVRMCExpr const *AVRExpr = cast<AVRMCExpr>(Expr);
|
||||
int64_t Result;
|
||||
if (AVRExpr->evaluateAsConstant(Result)) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
MCFixupKind FixupKind = static_cast<MCFixupKind>(AVRExpr->getFixupKind());
|
||||
Fixups.push_back(MCFixup::create(0, AVRExpr, FixupKind));
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(Kind == MCExpr::SymbolRef);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned AVRMCCodeEmitter::getMachineOpValue(const MCInst &MI,
|
||||
const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
|
||||
if (MO.isImm()) return static_cast<unsigned>(MO.getImm());
|
||||
|
||||
if (MO.isFPImm())
|
||||
return static_cast<unsigned>(APFloat(MO.getFPImm())
|
||||
.bitcastToAPInt()
|
||||
.getHiBits(32)
|
||||
.getLimitedValue());
|
||||
|
||||
// MO must be an Expr.
|
||||
assert(MO.isExpr());
|
||||
|
||||
return getExprOpValue(MO.getExpr(), Fixups, STI);
|
||||
}
|
||||
|
||||
void AVRMCCodeEmitter::emitInstruction(uint64_t Val, unsigned Size,
|
||||
const MCSubtargetInfo &STI,
|
||||
raw_ostream &OS) const {
|
||||
const uint16_t *Words = reinterpret_cast<uint16_t const *>(&Val);
|
||||
size_t WordCount = Size / 2;
|
||||
|
||||
for (int64_t i = WordCount - 1; i >= 0; --i) {
|
||||
uint16_t Word = Words[i];
|
||||
|
||||
OS << (uint8_t) ((Word & 0x00ff) >> 0);
|
||||
OS << (uint8_t) ((Word & 0xff00) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
void AVRMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
|
||||
|
||||
// Get byte count of instruction
|
||||
unsigned Size = Desc.getSize();
|
||||
|
||||
assert(Size > 0 && "Instruction size cannot be zero");
|
||||
|
||||
uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);
|
||||
emitInstruction(BinaryOpCode, Size, STI, OS);
|
||||
}
|
||||
|
||||
MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx) {
|
||||
return new AVRMCCodeEmitter(MCII, Ctx);
|
||||
}
|
||||
|
||||
#include "AVRGenMCCodeEmitter.inc"
|
||||
|
||||
} // end of namespace llvm
|
@ -1,116 +0,0 @@
|
||||
//===-- AVRMCCodeEmitter.h - Convert AVR Code to Machine Code -------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the AVRMCCodeEmitter class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
#ifndef LLVM_AVR_CODE_EMITTER_H
|
||||
#define LLVM_AVR_CODE_EMITTER_H
|
||||
|
||||
#include "AVRFixupKinds.h"
|
||||
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
#define GET_INSTRINFO_OPERAND_TYPES_ENUM
|
||||
#include "AVRGenInstrInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCContext;
|
||||
class MCExpr;
|
||||
class MCFixup;
|
||||
class MCInst;
|
||||
class MCInstrInfo;
|
||||
class MCOperand;
|
||||
class MCSubtargetInfo;
|
||||
class raw_ostream;
|
||||
|
||||
/// Writes AVR machine code to a stream.
|
||||
class AVRMCCodeEmitter : public MCCodeEmitter {
|
||||
public:
|
||||
AVRMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
|
||||
: MCII(MCII), Ctx(Ctx) {}
|
||||
|
||||
private:
|
||||
/// Finishes up encoding an LD/ST instruction.
|
||||
/// The purpose of this function is to set an bit in the instruction
|
||||
/// which follows no logical pattern. See the implementation for details.
|
||||
unsigned loadStorePostEncoder(const MCInst &MI, unsigned EncodedValue,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// Gets the encoding for a conditional branch target.
|
||||
template <AVR::Fixups Fixup>
|
||||
unsigned encodeRelCondBrTarget(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// Encodes the `PTRREGS` operand to a load or store instruction.
|
||||
unsigned encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// Encodes a `register+immediate` operand for `LDD`/`STD`.
|
||||
unsigned encodeMemri(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// Takes the complement of a number (~0 - val).
|
||||
unsigned encodeComplement(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// Encodes an immediate value with a given fixup.
|
||||
/// \tparam Offset The offset into the instruction for the fixup.
|
||||
template <AVR::Fixups Fixup, unsigned Offset>
|
||||
unsigned encodeImm(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// Gets the encoding of the target for the `CALL k` instruction.
|
||||
unsigned encodeCallTarget(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// TableGen'ed function to get the binary encoding for an instruction.
|
||||
uint64_t getBinaryCodeForInstr(const MCInst &MI,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// Returns the binary encoding of operand.
|
||||
///
|
||||
/// If the machine operand requires relocation, the relocation is recorded
|
||||
/// and zero is returned.
|
||||
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
void emitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI,
|
||||
raw_ostream &OS) const;
|
||||
|
||||
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
||||
AVRMCCodeEmitter(const AVRMCCodeEmitter &) = delete;
|
||||
void operator=(const AVRMCCodeEmitter &) = delete;
|
||||
|
||||
const MCInstrInfo &MCII;
|
||||
MCContext &Ctx;
|
||||
};
|
||||
|
||||
} // end namespace of llvm.
|
||||
|
||||
#endif // LLVM_AVR_CODE_EMITTER_H
|
||||
|
@ -1,51 +0,0 @@
|
||||
//===--------- AVRMCELFStreamer.cpp - AVR subclass of MCELFStreamer -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a stub that parses a MCInst bundle and passes the
|
||||
// instructions on to the real streamer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#define DEBUG_TYPE "avrmcelfstreamer"
|
||||
|
||||
#include "MCTargetDesc/AVRMCELFStreamer.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void AVRMCELFStreamer::EmitValueForModiferKind(
|
||||
const MCSymbol *Sym, unsigned SizeInBytes, SMLoc Loc,
|
||||
AVRMCExpr::VariantKind ModifierKind) {
|
||||
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_AVR_NONE;
|
||||
if (ModifierKind == AVRMCExpr::VK_AVR_None) {
|
||||
Kind = MCSymbolRefExpr::VK_AVR_DIFF8;
|
||||
if (SizeInBytes == SIZE_LONG)
|
||||
Kind = MCSymbolRefExpr::VK_AVR_DIFF32;
|
||||
else if (SizeInBytes == SIZE_WORD)
|
||||
Kind = MCSymbolRefExpr::VK_AVR_DIFF16;
|
||||
} else if (ModifierKind == AVRMCExpr::VK_AVR_LO8)
|
||||
Kind = MCSymbolRefExpr::VK_AVR_LO8;
|
||||
else if (ModifierKind == AVRMCExpr::VK_AVR_HI8)
|
||||
Kind = MCSymbolRefExpr::VK_AVR_HI8;
|
||||
else if (ModifierKind == AVRMCExpr::VK_AVR_HH8)
|
||||
Kind = MCSymbolRefExpr::VK_AVR_HLO8;
|
||||
MCELFStreamer::EmitValue(MCSymbolRefExpr::create(Sym, Kind, getContext()),
|
||||
SizeInBytes, Loc);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
MCStreamer *createAVRELFStreamer(Triple const &TT, MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> CE) {
|
||||
return new AVRMCELFStreamer(Context, std::move(MAB), OS, std::move(CE));
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
@ -1,54 +0,0 @@
|
||||
//===--------- AVRMCELFStreamer.h - AVR subclass of MCELFStreamer ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AVR_MCTARGETDESC_AVRMCELFSTREAMER_H
|
||||
#define LLVM_LIB_TARGET_AVR_MCTARGETDESC_AVRMCELFSTREAMER_H
|
||||
|
||||
#include "MCTargetDesc/AVRMCExpr.h"
|
||||
#include "MCTargetDesc/AVRMCTargetDesc.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
const int SIZE_LONG = 4;
|
||||
const int SIZE_WORD = 2;
|
||||
|
||||
class AVRMCELFStreamer : public MCELFStreamer {
|
||||
std::unique_ptr<MCInstrInfo> MCII;
|
||||
|
||||
public:
|
||||
AVRMCELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter)
|
||||
: MCELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)),
|
||||
MCII(createAVRMCInstrInfo()) {}
|
||||
|
||||
AVRMCELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> Emitter,
|
||||
MCAssembler *Assembler)
|
||||
: MCELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)),
|
||||
MCII(createAVRMCInstrInfo()) {}
|
||||
|
||||
void EmitValueForModiferKind(
|
||||
const MCSymbol *Sym, unsigned SizeInBytes, SMLoc Loc = SMLoc(),
|
||||
AVRMCExpr::VariantKind ModifierKind = AVRMCExpr::VK_AVR_None);
|
||||
};
|
||||
|
||||
MCStreamer *createAVRELFStreamer(Triple const &TT, MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> CE);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_AVR_MCTARGETDESC_AVRMCELFSTREAMER_H
|
@ -1,215 +0,0 @@
|
||||
//===-- AVRMCExpr.cpp - AVR specific MC expression classes ----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AVRMCExpr.h"
|
||||
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace {
|
||||
|
||||
const struct ModifierEntry {
|
||||
const char * const Spelling;
|
||||
AVRMCExpr::VariantKind VariantKind;
|
||||
} ModifierNames[] = {
|
||||
{"lo8", AVRMCExpr::VK_AVR_LO8}, {"hi8", AVRMCExpr::VK_AVR_HI8},
|
||||
{"hh8", AVRMCExpr::VK_AVR_HH8}, // synonym with hlo8
|
||||
{"hlo8", AVRMCExpr::VK_AVR_HH8}, {"hhi8", AVRMCExpr::VK_AVR_HHI8},
|
||||
|
||||
{"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8}, {"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8},
|
||||
{"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8},
|
||||
|
||||
{"lo8_gs", AVRMCExpr::VK_AVR_LO8_GS}, {"hi8_gs", AVRMCExpr::VK_AVR_HI8_GS},
|
||||
{"gs", AVRMCExpr::VK_AVR_GS},
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
const AVRMCExpr *AVRMCExpr::create(VariantKind Kind, const MCExpr *Expr,
|
||||
bool Negated, MCContext &Ctx) {
|
||||
return new (Ctx) AVRMCExpr(Kind, Expr, Negated);
|
||||
}
|
||||
|
||||
void AVRMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
|
||||
assert(Kind != VK_AVR_None);
|
||||
|
||||
if (isNegated())
|
||||
OS << '-';
|
||||
|
||||
OS << getName() << '(';
|
||||
getSubExpr()->print(OS, MAI);
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
bool AVRMCExpr::evaluateAsConstant(int64_t &Result) const {
|
||||
MCValue Value;
|
||||
|
||||
bool isRelocatable =
|
||||
getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr);
|
||||
|
||||
if (!isRelocatable)
|
||||
return false;
|
||||
|
||||
if (Value.isAbsolute()) {
|
||||
Result = evaluateAsInt64(Value.getConstant());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const {
|
||||
MCValue Value;
|
||||
bool isRelocatable = SubExpr->evaluateAsRelocatable(Value, Layout, Fixup);
|
||||
|
||||
if (!isRelocatable)
|
||||
return false;
|
||||
|
||||
if (Value.isAbsolute()) {
|
||||
Result = MCValue::get(evaluateAsInt64(Value.getConstant()));
|
||||
} else {
|
||||
if (!Layout) return false;
|
||||
|
||||
MCContext &Context = Layout->getAssembler().getContext();
|
||||
const MCSymbolRefExpr *Sym = Value.getSymA();
|
||||
MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
|
||||
if (Modifier != MCSymbolRefExpr::VK_None)
|
||||
return false;
|
||||
|
||||
Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
|
||||
Result = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const {
|
||||
if (Negated)
|
||||
Value *= -1;
|
||||
|
||||
switch (Kind) {
|
||||
case AVRMCExpr::VK_AVR_LO8:
|
||||
Value &= 0xff;
|
||||
break;
|
||||
case AVRMCExpr::VK_AVR_HI8:
|
||||
Value &= 0xff00;
|
||||
Value >>= 8;
|
||||
break;
|
||||
case AVRMCExpr::VK_AVR_HH8:
|
||||
Value &= 0xff0000;
|
||||
Value >>= 16;
|
||||
break;
|
||||
case AVRMCExpr::VK_AVR_HHI8:
|
||||
Value &= 0xff000000;
|
||||
Value >>= 24;
|
||||
break;
|
||||
case AVRMCExpr::VK_AVR_PM_LO8:
|
||||
case AVRMCExpr::VK_AVR_LO8_GS:
|
||||
Value >>= 1; // Program memory addresses must always be shifted by one.
|
||||
Value &= 0xff;
|
||||
break;
|
||||
case AVRMCExpr::VK_AVR_PM_HI8:
|
||||
case AVRMCExpr::VK_AVR_HI8_GS:
|
||||
Value >>= 1; // Program memory addresses must always be shifted by one.
|
||||
Value &= 0xff00;
|
||||
Value >>= 8;
|
||||
break;
|
||||
case AVRMCExpr::VK_AVR_PM_HH8:
|
||||
Value >>= 1; // Program memory addresses must always be shifted by one.
|
||||
Value &= 0xff0000;
|
||||
Value >>= 16;
|
||||
break;
|
||||
case AVRMCExpr::VK_AVR_GS:
|
||||
Value >>= 1; // Program memory addresses must always be shifted by one.
|
||||
break;
|
||||
|
||||
case AVRMCExpr::VK_AVR_None:
|
||||
llvm_unreachable("Uninitialized expression.");
|
||||
}
|
||||
return static_cast<uint64_t>(Value) & 0xff;
|
||||
}
|
||||
|
||||
AVR::Fixups AVRMCExpr::getFixupKind() const {
|
||||
AVR::Fixups Kind = AVR::Fixups::LastTargetFixupKind;
|
||||
|
||||
switch (getKind()) {
|
||||
case VK_AVR_LO8:
|
||||
Kind = isNegated() ? AVR::fixup_lo8_ldi_neg : AVR::fixup_lo8_ldi;
|
||||
break;
|
||||
case VK_AVR_HI8:
|
||||
Kind = isNegated() ? AVR::fixup_hi8_ldi_neg : AVR::fixup_hi8_ldi;
|
||||
break;
|
||||
case VK_AVR_HH8:
|
||||
Kind = isNegated() ? AVR::fixup_hh8_ldi_neg : AVR::fixup_hh8_ldi;
|
||||
break;
|
||||
case VK_AVR_HHI8:
|
||||
Kind = isNegated() ? AVR::fixup_ms8_ldi_neg : AVR::fixup_ms8_ldi;
|
||||
break;
|
||||
|
||||
case VK_AVR_PM_LO8:
|
||||
Kind = isNegated() ? AVR::fixup_lo8_ldi_pm_neg : AVR::fixup_lo8_ldi_pm;
|
||||
break;
|
||||
case VK_AVR_PM_HI8:
|
||||
Kind = isNegated() ? AVR::fixup_hi8_ldi_pm_neg : AVR::fixup_hi8_ldi_pm;
|
||||
break;
|
||||
case VK_AVR_PM_HH8:
|
||||
Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm;
|
||||
break;
|
||||
case VK_AVR_GS:
|
||||
Kind = AVR::fixup_16_pm;
|
||||
break;
|
||||
case VK_AVR_LO8_GS:
|
||||
Kind = AVR::fixup_lo8_ldi_gs;
|
||||
break;
|
||||
case VK_AVR_HI8_GS:
|
||||
Kind = AVR::fixup_hi8_ldi_gs;
|
||||
break;
|
||||
|
||||
case VK_AVR_None:
|
||||
llvm_unreachable("Uninitialized expression");
|
||||
}
|
||||
|
||||
return Kind;
|
||||
}
|
||||
|
||||
void AVRMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
|
||||
Streamer.visitUsedExpr(*getSubExpr());
|
||||
}
|
||||
|
||||
const char *AVRMCExpr::getName() const {
|
||||
const auto &Modifier = std::find_if(
|
||||
std::begin(ModifierNames), std::end(ModifierNames),
|
||||
[this](ModifierEntry const &Mod) { return Mod.VariantKind == Kind; });
|
||||
|
||||
if (Modifier != std::end(ModifierNames)) {
|
||||
return Modifier->Spelling;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AVRMCExpr::VariantKind AVRMCExpr::getKindByName(StringRef Name) {
|
||||
const auto &Modifier = std::find_if(
|
||||
std::begin(ModifierNames), std::end(ModifierNames),
|
||||
[&Name](ModifierEntry const &Mod) { return Mod.Spelling == Name; });
|
||||
|
||||
if (Modifier != std::end(ModifierNames)) {
|
||||
return Modifier->VariantKind;
|
||||
}
|
||||
return VK_AVR_None;
|
||||
}
|
||||
|
||||
} // end of namespace llvm
|
||||
|
@ -1,92 +0,0 @@
|
||||
//===-- AVRMCExpr.h - AVR specific MC expression classes --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_AVR_MCEXPR_H
|
||||
#define LLVM_AVR_MCEXPR_H
|
||||
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
|
||||
#include "MCTargetDesc/AVRFixupKinds.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// A expression in AVR machine code.
|
||||
class AVRMCExpr : public MCTargetExpr {
|
||||
public:
|
||||
/// Specifies the type of an expression.
|
||||
enum VariantKind {
|
||||
VK_AVR_None,
|
||||
|
||||
VK_AVR_HI8, ///< Corresponds to `hi8()`.
|
||||
VK_AVR_LO8, ///< Corresponds to `lo8()`.
|
||||
VK_AVR_HH8, ///< Corresponds to `hlo8() and hh8()`.
|
||||
VK_AVR_HHI8, ///< Corresponds to `hhi8()`.
|
||||
|
||||
VK_AVR_PM_LO8, ///< Corresponds to `pm_lo8()`.
|
||||
VK_AVR_PM_HI8, ///< Corresponds to `pm_hi8()`.
|
||||
VK_AVR_PM_HH8, ///< Corresponds to `pm_hh8()`.
|
||||
|
||||
VK_AVR_LO8_GS, ///< Corresponds to `lo8(gs())`.
|
||||
VK_AVR_HI8_GS, ///< Corresponds to `hi8(gs())`.
|
||||
VK_AVR_GS, ///< Corresponds to `gs()`.
|
||||
};
|
||||
|
||||
public:
|
||||
/// Creates an AVR machine code expression.
|
||||
static const AVRMCExpr *create(VariantKind Kind, const MCExpr *Expr,
|
||||
bool isNegated, MCContext &Ctx);
|
||||
|
||||
/// Gets the type of the expression.
|
||||
VariantKind getKind() const { return Kind; }
|
||||
/// Gets the name of the expression.
|
||||
const char *getName() const;
|
||||
const MCExpr *getSubExpr() const { return SubExpr; }
|
||||
/// Gets the fixup which corresponds to the expression.
|
||||
AVR::Fixups getFixupKind() const;
|
||||
/// Evaluates the fixup as a constant value.
|
||||
bool evaluateAsConstant(int64_t &Result) const;
|
||||
|
||||
bool isNegated() const { return Negated; }
|
||||
void setNegated(bool negated = true) { Negated = negated; }
|
||||
|
||||
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
|
||||
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const override;
|
||||
|
||||
void visitUsedExpr(MCStreamer &streamer) const override;
|
||||
|
||||
MCFragment *findAssociatedFragment() const override {
|
||||
return getSubExpr()->findAssociatedFragment();
|
||||
}
|
||||
|
||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
||||
|
||||
static bool classof(const MCExpr *E) {
|
||||
return E->getKind() == MCExpr::Target;
|
||||
}
|
||||
|
||||
public:
|
||||
static VariantKind getKindByName(StringRef Name);
|
||||
|
||||
private:
|
||||
int64_t evaluateAsInt64(int64_t Value) const;
|
||||
|
||||
const VariantKind Kind;
|
||||
const MCExpr *SubExpr;
|
||||
bool Negated;
|
||||
|
||||
private:
|
||||
explicit AVRMCExpr(VariantKind Kind, const MCExpr *Expr, bool Negated)
|
||||
: Kind(Kind), SubExpr(Expr), Negated(Negated) {}
|
||||
~AVRMCExpr() {}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_AVR_MCEXPR_H
|
@ -1,127 +0,0 @@
|
||||
//===-- AVRMCTargetDesc.cpp - AVR Target Descriptions ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides AVR specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AVRELFStreamer.h"
|
||||
#include "AVRMCAsmInfo.h"
|
||||
#include "AVRMCELFStreamer.h"
|
||||
#include "AVRMCTargetDesc.h"
|
||||
#include "AVRTargetStreamer.h"
|
||||
#include "InstPrinter/AVRInstPrinter.h"
|
||||
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
#define GET_INSTRINFO_MC_DESC
|
||||
#include "AVRGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_MC_DESC
|
||||
#include "AVRGenSubtargetInfo.inc"
|
||||
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#include "AVRGenRegisterInfo.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MCInstrInfo *llvm::createAVRMCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitAVRMCInstrInfo(X);
|
||||
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createAVRMCRegisterInfo(const Triple &TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitAVRMCRegisterInfo(X, 0);
|
||||
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCSubtargetInfo *createAVRMCSubtargetInfo(const Triple &TT,
|
||||
StringRef CPU, StringRef FS) {
|
||||
return createAVRMCSubtargetInfoImpl(TT, CPU, FS);
|
||||
}
|
||||
|
||||
static MCInstPrinter *createAVRMCInstPrinter(const Triple &T,
|
||||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI) {
|
||||
if (SyntaxVariant == 0) {
|
||||
return new AVRInstPrinter(MAI, MII, MRI);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> &&MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter,
|
||||
bool RelaxAll) {
|
||||
return createELFStreamer(Context, std::move(MAB), OS,
|
||||
std::move(Emitter), RelaxAll);
|
||||
}
|
||||
|
||||
static MCTargetStreamer *
|
||||
createAVRObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
|
||||
return new AVRELFStreamer(S, STI);
|
||||
}
|
||||
|
||||
static MCTargetStreamer *createMCAsmTargetStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS,
|
||||
MCInstPrinter *InstPrint,
|
||||
bool isVerboseAsm) {
|
||||
return new AVRTargetAsmStreamer(S);
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeAVRTargetMC() {
|
||||
// Register the MC asm info.
|
||||
RegisterMCAsmInfo<AVRMCAsmInfo> X(getTheAVRTarget());
|
||||
|
||||
// Register the MC instruction info.
|
||||
TargetRegistry::RegisterMCInstrInfo(getTheAVRTarget(), createAVRMCInstrInfo);
|
||||
|
||||
// Register the MC register info.
|
||||
TargetRegistry::RegisterMCRegInfo(getTheAVRTarget(), createAVRMCRegisterInfo);
|
||||
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(getTheAVRTarget(),
|
||||
createAVRMCSubtargetInfo);
|
||||
|
||||
// Register the MCInstPrinter.
|
||||
TargetRegistry::RegisterMCInstPrinter(getTheAVRTarget(),
|
||||
createAVRMCInstPrinter);
|
||||
|
||||
// Register the MC Code Emitter
|
||||
TargetRegistry::RegisterMCCodeEmitter(getTheAVRTarget(), createAVRMCCodeEmitter);
|
||||
|
||||
// Register the obj streamer
|
||||
TargetRegistry::RegisterELFStreamer(getTheAVRTarget(), createMCStreamer);
|
||||
|
||||
// Register the obj target streamer.
|
||||
TargetRegistry::RegisterObjectTargetStreamer(getTheAVRTarget(),
|
||||
createAVRObjectTargetStreamer);
|
||||
|
||||
// Register the asm target streamer.
|
||||
TargetRegistry::RegisterAsmTargetStreamer(getTheAVRTarget(),
|
||||
createMCAsmTargetStreamer);
|
||||
|
||||
// Register the asm backend (as little endian).
|
||||
TargetRegistry::RegisterMCAsmBackend(getTheAVRTarget(), createAVRAsmBackend);
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
//===-- AVRMCTargetDesc.h - AVR Target Descriptions -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides AVR specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_AVR_MCTARGET_DESC_H
|
||||
#define LLVM_AVR_MCTARGET_DESC_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCAsmBackend;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCObjectWriter;
|
||||
class MCRegisterInfo;
|
||||
class MCSubtargetInfo;
|
||||
class MCTargetOptions;
|
||||
class StringRef;
|
||||
class Target;
|
||||
class Triple;
|
||||
class raw_pwrite_stream;
|
||||
|
||||
Target &getTheAVRTarget();
|
||||
|
||||
MCInstrInfo *createAVRMCInstrInfo();
|
||||
|
||||
/// Creates a machine code emitter for AVR.
|
||||
MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx);
|
||||
|
||||
/// Creates an assembly backend for AVR.
|
||||
MCAsmBackend *createAVRAsmBackend(const Target &T, const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const llvm::MCTargetOptions &TO);
|
||||
|
||||
/// Creates an ELF object writer for AVR.
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createAVRELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "AVRGenRegisterInfo.inc"
|
||||
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "AVRGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "AVRGenSubtargetInfo.inc"
|
||||
|
||||
#endif // LLVM_AVR_MCTARGET_DESC_H
|
@ -1,44 +0,0 @@
|
||||
//===-- AVRTargetStreamer.cpp - AVR Target Streamer Methods ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides AVR specific target streamer methods.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AVRTargetStreamer.h"
|
||||
|
||||
#include "llvm/MC/MCContext.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
AVRTargetStreamer::AVRTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
|
||||
|
||||
AVRTargetAsmStreamer::AVRTargetAsmStreamer(MCStreamer &S)
|
||||
: AVRTargetStreamer(S) {}
|
||||
|
||||
void AVRTargetStreamer::finish() {
|
||||
MCStreamer &OS = getStreamer();
|
||||
MCContext &Context = OS.getContext();
|
||||
|
||||
MCSymbol *DoCopyData = Context.getOrCreateSymbol("__do_copy_data");
|
||||
MCSymbol *DoClearBss = Context.getOrCreateSymbol("__do_clear_bss");
|
||||
|
||||
// FIXME: We can disable __do_copy_data if there are no static RAM variables.
|
||||
|
||||
OS.emitRawComment(" Declaring this symbol tells the CRT that it should");
|
||||
OS.emitRawComment("copy all variables from program memory to RAM on startup");
|
||||
OS.EmitSymbolAttribute(DoCopyData, MCSA_Global);
|
||||
|
||||
OS.emitRawComment(" Declaring this symbol tells the CRT that it should");
|
||||
OS.emitRawComment("clear the zeroed data section on startup");
|
||||
OS.EmitSymbolAttribute(DoClearBss, MCSA_Global);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -1,34 +0,0 @@
|
||||
//===-- AVRTargetStreamer.h - AVR Target Streamer --------------*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_AVR_TARGET_STREAMER_H
|
||||
#define LLVM_AVR_TARGET_STREAMER_H
|
||||
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCStreamer;
|
||||
|
||||
/// A generic AVR target output stream.
|
||||
class AVRTargetStreamer : public MCTargetStreamer {
|
||||
public:
|
||||
explicit AVRTargetStreamer(MCStreamer &S);
|
||||
|
||||
void finish() override;
|
||||
};
|
||||
|
||||
/// A target streamer for textual AVR assembly code.
|
||||
class AVRTargetAsmStreamer : public AVRTargetStreamer {
|
||||
public:
|
||||
explicit AVRTargetAsmStreamer(MCStreamer &S);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_AVR_TARGET_STREAMER_H
|
@ -1,14 +0,0 @@
|
||||
add_llvm_library(LLVMAVRDesc
|
||||
AVRAsmBackend.cpp
|
||||
AVRELFObjectWriter.cpp
|
||||
AVRELFStreamer.cpp
|
||||
AVRMCAsmInfo.cpp
|
||||
AVRMCCodeEmitter.cpp
|
||||
AVRMCELFStreamer.cpp
|
||||
AVRMCExpr.cpp
|
||||
AVRMCTargetDesc.cpp
|
||||
AVRTargetStreamer.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMAVRDesc AVRCommonTableGen)
|
||||
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/AVR/MCTargetDesc/LLVMBuild.txt --------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = AVRDesc
|
||||
parent = AVR
|
||||
required_libraries = MC AVRAsmPrinter AVRInfo Support
|
||||
add_to_library_groups = AVR
|
Reference in New Issue
Block a user