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