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());
}
|