1 //===-- AVRMCExpr.cpp - AVR specific MC expression classes ----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "AVRMCExpr.h"
11
12 #include "llvm/MC/MCAsmLayout.h"
13 #include "llvm/MC/MCAssembler.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCStreamer.h"
16 #include "llvm/MC/MCValue.h"
17
18 namespace llvm {
19
20 namespace {
21
22 const struct ModifierEntry {
23 const char * const Spelling;
24 AVRMCExpr::VariantKind VariantKind;
25 } ModifierNames[] = {
26 {"lo8", AVRMCExpr::VK_AVR_LO8}, {"hi8", AVRMCExpr::VK_AVR_HI8},
27 {"hh8", AVRMCExpr::VK_AVR_HH8}, // synonym with hlo8
28 {"hlo8", AVRMCExpr::VK_AVR_HH8}, {"hhi8", AVRMCExpr::VK_AVR_HHI8},
29
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
92 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
93 Result = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
94 }
95
96 return true;
97 }
98
evaluateAsInt64(int64_t Value) const99 int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const {
100 if (Negated)
101 Value *= -1;
102
103 switch (Kind) {
104 case AVRMCExpr::VK_AVR_LO8:
105 Value &= 0xff;
106 break;
107 case AVRMCExpr::VK_AVR_HI8:
108 Value &= 0xff00;
109 Value >>= 8;
110 break;
111 case AVRMCExpr::VK_AVR_HH8:
112 Value &= 0xff0000;
113 Value >>= 16;
114 break;
115 case AVRMCExpr::VK_AVR_HHI8:
116 Value &= 0xff000000;
117 Value >>= 24;
118 break;
119 case AVRMCExpr::VK_AVR_PM_LO8:
120 case AVRMCExpr::VK_AVR_LO8_GS:
121 Value >>= 1; // Program memory addresses must always be shifted by one.
122 Value &= 0xff;
123 break;
124 case AVRMCExpr::VK_AVR_PM_HI8:
125 case AVRMCExpr::VK_AVR_HI8_GS:
126 Value >>= 1; // Program memory addresses must always be shifted by one.
127 Value &= 0xff00;
128 Value >>= 8;
129 break;
130 case AVRMCExpr::VK_AVR_PM_HH8:
131 Value >>= 1; // Program memory addresses must always be shifted by one.
132 Value &= 0xff0000;
133 Value >>= 16;
134 break;
135 case AVRMCExpr::VK_AVR_GS:
136 Value >>= 1; // Program memory addresses must always be shifted by one.
137 break;
138
139 case AVRMCExpr::VK_AVR_None:
140 llvm_unreachable("Uninitialized expression.");
141 }
142 return static_cast<uint64_t>(Value) & 0xff;
143 }
144
getFixupKind() const145 AVR::Fixups AVRMCExpr::getFixupKind() const {
146 AVR::Fixups Kind = AVR::Fixups::LastTargetFixupKind;
147
148 switch (getKind()) {
149 case VK_AVR_LO8:
150 Kind = isNegated() ? AVR::fixup_lo8_ldi_neg : AVR::fixup_lo8_ldi;
151 break;
152 case VK_AVR_HI8:
153 Kind = isNegated() ? AVR::fixup_hi8_ldi_neg : AVR::fixup_hi8_ldi;
154 break;
155 case VK_AVR_HH8:
156 Kind = isNegated() ? AVR::fixup_hh8_ldi_neg : AVR::fixup_hh8_ldi;
157 break;
158 case VK_AVR_HHI8:
159 Kind = isNegated() ? AVR::fixup_ms8_ldi_neg : AVR::fixup_ms8_ldi;
160 break;
161
162 case VK_AVR_PM_LO8:
163 Kind = isNegated() ? AVR::fixup_lo8_ldi_pm_neg : AVR::fixup_lo8_ldi_pm;
164 break;
165 case VK_AVR_PM_HI8:
166 Kind = isNegated() ? AVR::fixup_hi8_ldi_pm_neg : AVR::fixup_hi8_ldi_pm;
167 break;
168 case VK_AVR_PM_HH8:
169 Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm;
170 break;
171 case VK_AVR_GS:
172 Kind = AVR::fixup_16_pm;
173 break;
174 case VK_AVR_LO8_GS:
175 Kind = AVR::fixup_lo8_ldi_gs;
176 break;
177 case VK_AVR_HI8_GS:
178 Kind = AVR::fixup_hi8_ldi_gs;
179 break;
180
181 case VK_AVR_None:
182 llvm_unreachable("Uninitialized expression");
183 }
184
185 return Kind;
186 }
187
visitUsedExpr(MCStreamer & Streamer) const188 void AVRMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
189 Streamer.visitUsedExpr(*getSubExpr());
190 }
191
getName() const192 const char *AVRMCExpr::getName() const {
193 const auto &Modifier = std::find_if(
194 std::begin(ModifierNames), std::end(ModifierNames),
195 [this](ModifierEntry const &Mod) { return Mod.VariantKind == Kind; });
196
197 if (Modifier != std::end(ModifierNames)) {
198 return Modifier->Spelling;
199 }
200 return nullptr;
201 }
202
getKindByName(StringRef Name)203 AVRMCExpr::VariantKind AVRMCExpr::getKindByName(StringRef Name) {
204 const auto &Modifier = std::find_if(
205 std::begin(ModifierNames), std::end(ModifierNames),
206 [&Name](ModifierEntry const &Mod) { return Mod.Spelling == Name; });
207
208 if (Modifier != std::end(ModifierNames)) {
209 return Modifier->VariantKind;
210 }
211 return VK_AVR_None;
212 }
213
214 } // end of namespace llvm
215
216