Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp
35294 views
1
//===-- AVRMCExpr.cpp - AVR specific MC expression classes ----------------===//
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "AVRMCExpr.h"
10
11
#include "llvm/MC/MCAssembler.h"
12
#include "llvm/MC/MCContext.h"
13
#include "llvm/MC/MCStreamer.h"
14
#include "llvm/MC/MCValue.h"
15
16
namespace llvm {
17
18
namespace {
19
20
const struct ModifierEntry {
21
const char *const Spelling;
22
AVRMCExpr::VariantKind VariantKind;
23
} ModifierNames[] = {
24
{"lo8", AVRMCExpr::VK_AVR_LO8}, {"hi8", AVRMCExpr::VK_AVR_HI8},
25
{"hh8", AVRMCExpr::VK_AVR_HH8}, // synonym with hlo8
26
{"hlo8", AVRMCExpr::VK_AVR_HH8}, {"hhi8", AVRMCExpr::VK_AVR_HHI8},
27
28
{"pm", AVRMCExpr::VK_AVR_PM}, {"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8},
29
{"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8}, {"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8},
30
31
{"lo8_gs", AVRMCExpr::VK_AVR_LO8_GS}, {"hi8_gs", AVRMCExpr::VK_AVR_HI8_GS},
32
{"gs", AVRMCExpr::VK_AVR_GS},
33
};
34
35
} // end of anonymous namespace
36
37
const AVRMCExpr *AVRMCExpr::create(VariantKind Kind, const MCExpr *Expr,
38
bool Negated, MCContext &Ctx) {
39
return new (Ctx) AVRMCExpr(Kind, Expr, Negated);
40
}
41
42
void AVRMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
43
assert(Kind != VK_AVR_None);
44
OS << getName() << '(';
45
if (isNegated())
46
OS << '-' << '(';
47
getSubExpr()->print(OS, MAI);
48
if (isNegated())
49
OS << ')';
50
OS << ')';
51
}
52
53
bool AVRMCExpr::evaluateAsConstant(int64_t &Result) const {
54
MCValue Value;
55
56
bool isRelocatable =
57
getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr);
58
59
if (!isRelocatable)
60
return false;
61
62
if (Value.isAbsolute()) {
63
Result = evaluateAsInt64(Value.getConstant());
64
return true;
65
}
66
67
return false;
68
}
69
70
bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result,
71
const MCAssembler *Asm,
72
const MCFixup *Fixup) const {
73
MCValue Value;
74
bool isRelocatable = SubExpr->evaluateAsRelocatable(Value, Asm, Fixup);
75
76
if (!isRelocatable)
77
return false;
78
79
if (Value.isAbsolute()) {
80
Result = MCValue::get(evaluateAsInt64(Value.getConstant()));
81
} else {
82
if (!Asm || !Asm->hasLayout())
83
return false;
84
85
MCContext &Context = Asm->getContext();
86
const MCSymbolRefExpr *Sym = Value.getSymA();
87
MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
88
if (Modifier != MCSymbolRefExpr::VK_None)
89
return false;
90
if (Kind == VK_AVR_PM) {
91
Modifier = MCSymbolRefExpr::VK_AVR_PM;
92
}
93
94
Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
95
Result = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
96
}
97
98
return true;
99
}
100
101
int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const {
102
if (Negated)
103
Value *= -1;
104
105
switch (Kind) {
106
case AVRMCExpr::VK_AVR_LO8:
107
Value &= 0xff;
108
break;
109
case AVRMCExpr::VK_AVR_HI8:
110
Value &= 0xff00;
111
Value >>= 8;
112
break;
113
case AVRMCExpr::VK_AVR_HH8:
114
Value &= 0xff0000;
115
Value >>= 16;
116
break;
117
case AVRMCExpr::VK_AVR_HHI8:
118
Value &= 0xff000000;
119
Value >>= 24;
120
break;
121
case AVRMCExpr::VK_AVR_PM_LO8:
122
case AVRMCExpr::VK_AVR_LO8_GS:
123
Value >>= 1; // Program memory addresses must always be shifted by one.
124
Value &= 0xff;
125
break;
126
case AVRMCExpr::VK_AVR_PM_HI8:
127
case AVRMCExpr::VK_AVR_HI8_GS:
128
Value >>= 1; // Program memory addresses must always be shifted by one.
129
Value &= 0xff00;
130
Value >>= 8;
131
break;
132
case AVRMCExpr::VK_AVR_PM_HH8:
133
Value >>= 1; // Program memory addresses must always be shifted by one.
134
Value &= 0xff0000;
135
Value >>= 16;
136
break;
137
case AVRMCExpr::VK_AVR_PM:
138
case AVRMCExpr::VK_AVR_GS:
139
Value >>= 1; // Program memory addresses must always be shifted by one.
140
break;
141
142
case AVRMCExpr::VK_AVR_None:
143
llvm_unreachable("Uninitialized expression.");
144
}
145
return static_cast<uint64_t>(Value) & 0xff;
146
}
147
148
AVR::Fixups AVRMCExpr::getFixupKind() const {
149
AVR::Fixups Kind = AVR::Fixups::LastTargetFixupKind;
150
151
switch (getKind()) {
152
case VK_AVR_LO8:
153
Kind = isNegated() ? AVR::fixup_lo8_ldi_neg : AVR::fixup_lo8_ldi;
154
break;
155
case VK_AVR_HI8:
156
Kind = isNegated() ? AVR::fixup_hi8_ldi_neg : AVR::fixup_hi8_ldi;
157
break;
158
case VK_AVR_HH8:
159
Kind = isNegated() ? AVR::fixup_hh8_ldi_neg : AVR::fixup_hh8_ldi;
160
break;
161
case VK_AVR_HHI8:
162
Kind = isNegated() ? AVR::fixup_ms8_ldi_neg : AVR::fixup_ms8_ldi;
163
break;
164
165
case VK_AVR_PM_LO8:
166
Kind = isNegated() ? AVR::fixup_lo8_ldi_pm_neg : AVR::fixup_lo8_ldi_pm;
167
break;
168
case VK_AVR_PM_HI8:
169
Kind = isNegated() ? AVR::fixup_hi8_ldi_pm_neg : AVR::fixup_hi8_ldi_pm;
170
break;
171
case VK_AVR_PM_HH8:
172
Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm;
173
break;
174
case VK_AVR_PM:
175
case VK_AVR_GS:
176
Kind = AVR::fixup_16_pm;
177
break;
178
case VK_AVR_LO8_GS:
179
Kind = AVR::fixup_lo8_ldi_gs;
180
break;
181
case VK_AVR_HI8_GS:
182
Kind = AVR::fixup_hi8_ldi_gs;
183
break;
184
185
case VK_AVR_None:
186
llvm_unreachable("Uninitialized expression");
187
}
188
189
return Kind;
190
}
191
192
void AVRMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
193
Streamer.visitUsedExpr(*getSubExpr());
194
}
195
196
const char *AVRMCExpr::getName() const {
197
const auto &Modifier =
198
llvm::find_if(ModifierNames, [this](ModifierEntry const &Mod) {
199
return Mod.VariantKind == Kind;
200
});
201
202
if (Modifier != std::end(ModifierNames)) {
203
return Modifier->Spelling;
204
}
205
return nullptr;
206
}
207
208
AVRMCExpr::VariantKind AVRMCExpr::getKindByName(StringRef Name) {
209
const auto &Modifier =
210
llvm::find_if(ModifierNames, [&Name](ModifierEntry const &Mod) {
211
return Mod.Spelling == Name;
212
});
213
214
if (Modifier != std::end(ModifierNames)) {
215
return Modifier->VariantKind;
216
}
217
return VK_AVR_None;
218
}
219
220
} // end of namespace llvm
221
222