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 | {.Spelling: "lo8" , .VariantKind: AVRMCExpr::VK_AVR_LO8}, {.Spelling: "hi8" , .VariantKind: AVRMCExpr::VK_AVR_HI8}, |
25 | {.Spelling: "hh8" , .VariantKind: AVRMCExpr::VK_AVR_HH8}, // synonym with hlo8 |
26 | {.Spelling: "hlo8" , .VariantKind: AVRMCExpr::VK_AVR_HH8}, {.Spelling: "hhi8" , .VariantKind: AVRMCExpr::VK_AVR_HHI8}, |
27 | |
28 | {.Spelling: "pm" , .VariantKind: AVRMCExpr::VK_AVR_PM}, {.Spelling: "pm_lo8" , .VariantKind: AVRMCExpr::VK_AVR_PM_LO8}, |
29 | {.Spelling: "pm_hi8" , .VariantKind: AVRMCExpr::VK_AVR_PM_HI8}, {.Spelling: "pm_hh8" , .VariantKind: AVRMCExpr::VK_AVR_PM_HH8}, |
30 | |
31 | {.Spelling: "lo8_gs" , .VariantKind: AVRMCExpr::VK_AVR_LO8_GS}, {.Spelling: "hi8_gs" , .VariantKind: AVRMCExpr::VK_AVR_HI8_GS}, |
32 | {.Spelling: "gs" , .VariantKind: 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(Res&: Value, Asm: nullptr, Fixup: nullptr); |
58 | |
59 | if (!isRelocatable) |
60 | return false; |
61 | |
62 | if (Value.isAbsolute()) { |
63 | Result = evaluateAsInt64(Value: 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(Res&: Value, Asm, Fixup); |
75 | |
76 | if (!isRelocatable) |
77 | return false; |
78 | |
79 | if (Value.isAbsolute()) { |
80 | Result = MCValue::get(Val: evaluateAsInt64(Value: 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(Symbol: &Sym->getSymbol(), Kind: Modifier, Ctx&: Context); |
95 | Result = MCValue::get(SymA: Sym, SymB: Value.getSymB(), Val: 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(Expr: *getSubExpr()); |
194 | } |
195 | |
196 | const char *AVRMCExpr::getName() const { |
197 | const auto &Modifier = |
198 | llvm::find_if(Range: ModifierNames, P: [this](ModifierEntry const &Mod) { |
199 | return Mod.VariantKind == Kind; |
200 | }); |
201 | |
202 | if (Modifier != std::end(arr: 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(Range: ModifierNames, P: [&Name](ModifierEntry const &Mod) { |
211 | return Mod.Spelling == Name; |
212 | }); |
213 | |
214 | if (Modifier != std::end(arr: ModifierNames)) { |
215 | return Modifier->VariantKind; |
216 | } |
217 | return VK_AVR_None; |
218 | } |
219 | |
220 | } // end of namespace llvm |
221 | |