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