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