1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
//===-- Nios2AsmBackend.cpp - Nios2 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 Nios2AsmBackend class.
//
//===----------------------------------------------------------------------===//
//
#include "MCTargetDesc/Nios2AsmBackend.h"
#include "MCTargetDesc/Nios2FixupKinds.h"
#include "MCTargetDesc/Nios2MCTargetDesc.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
using namespace llvm;
// Prepare value for the target space for it
static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value) {
unsigned Kind = Fixup.getKind();
// Add/subtract and shift
switch (Kind) {
default:
return 0;
case Nios2::fixup_Nios2_LO16:
break;
case Nios2::fixup_Nios2_HI16:
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
Value = ((Value + 0x8000) >> 16) & 0xffff;
break;
}
return Value;
}
// Calculate index for Nios2 specific little endian byte order
static unsigned calculateLEIndex(unsigned i) {
assert(i <= 3 && "Index out of range!");
return (1 - i / 2) * 2 + i % 2;
}
/// ApplyFixup - Apply the \p Value for given \p Fixup into the provided
/// data fragment, at the offset specified by the fixup and following the
/// fixup kind as appropriate.
void Nios2AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) const {
MCFixupKind Kind = Fixup.getKind();
Value = adjustFixupValue(Fixup, Value);
if (!Value)
return; // Doesn't change encoding.
// Where do we start in the object
unsigned Offset = Fixup.getOffset();
// Number of bytes we need to fixup
unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
// Grab current value, if any, from bits.
uint64_t CurVal = 0;
for (unsigned i = 0; i != NumBytes; ++i) {
unsigned Idx = calculateLEIndex(i);
CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i * 8);
}
uint64_t Mask = ((uint64_t)(-1) >> (64 - getFixupKindInfo(Kind).TargetSize));
CurVal |= Value & Mask;
// Write out the fixed up bytes back to the code/data bits.
for (unsigned i = 0; i != NumBytes; ++i) {
unsigned Idx = calculateLEIndex(i);
Data[Offset + Idx] = (uint8_t)((CurVal >> (i * 8)) & 0xff);
}
}
Optional<MCFixupKind> Nios2AsmBackend::getFixupKind(StringRef Name) const {
return StringSwitch<Optional<MCFixupKind>>(Name)
.Case("R_NIOS2_NONE", (MCFixupKind)Nios2::fixup_Nios2_32)
.Case("R_NIOS2_32", FK_Data_4)
.Default(MCAsmBackend::getFixupKind(Name));
}
//@getFixupKindInfo {
const MCFixupKindInfo &
Nios2AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[Nios2::NumTargetFixupKinds] = {
// This table *must* be in same the order of fixup_* kinds in
// Nios2FixupKinds.h.
//
// name offset bits flags
{"fixup_Nios2_32", 0, 32, 0},
{"fixup_Nios2_HI16", 0, 16, 0},
{"fixup_Nios2_LO16", 0, 16, 0}};
if (Kind < FirstTargetFixupKind)
return MCAsmBackend::getFixupKindInfo(Kind);
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
"Invalid kind!");
return Infos[Kind - FirstTargetFixupKind];
}
std::unique_ptr<MCObjectWriter>
Nios2AsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
return createNios2ELFObjectWriter(OS,
MCELFObjectTargetWriter::getOSABI(OSType));
}
bool Nios2AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
return true;
}
// MCAsmBackend
MCAsmBackend *llvm::createNios2AsmBackend(const Target &T,
const MCRegisterInfo &MRI,
const Triple &TT, StringRef CPU,
const MCTargetOptions &Options) {
return new Nios2AsmBackend(T, TT.getOS());
}
|