xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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     {"lo8", AVRMCExpr::VK_AVR_LO8},       {"hi8", AVRMCExpr::VK_AVR_HI8},
25     {"hh8", AVRMCExpr::VK_AVR_HH8}, // synonym with hlo8
26     {"hlo8", AVRMCExpr::VK_AVR_HH8},      {"hhi8", AVRMCExpr::VK_AVR_HHI8},
27 
28     {"pm", AVRMCExpr::VK_AVR_PM},         {"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8},
29     {"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8}, {"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8},
30 
31     {"lo8_gs", AVRMCExpr::VK_AVR_LO8_GS}, {"hi8_gs", AVRMCExpr::VK_AVR_HI8_GS},
32     {"gs", AVRMCExpr::VK_AVR_GS},
33 };
34 
35 } // end of anonymous namespace
36 
create(VariantKind Kind,const MCExpr * Expr,bool Negated,MCContext & Ctx)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 
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const42 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 
evaluateAsConstant(int64_t & Result) const53 bool AVRMCExpr::evaluateAsConstant(int64_t &Result) const {
54   MCValue Value;
55 
56   bool isRelocatable =
57       getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr);
58 
59   if (!isRelocatable)
60     return false;
61 
62   if (Value.isAbsolute()) {
63     Result = evaluateAsInt64(Value.getConstant());
64     return true;
65   }
66 
67   return false;
68 }
69 
evaluateAsRelocatableImpl(MCValue & Result,const MCAssembler * Asm,const MCFixup * Fixup) const70 bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result,
71                                           const MCAssembler *Asm,
72                                           const MCFixup *Fixup) const {
73   MCValue Value;
74   bool isRelocatable = SubExpr->evaluateAsRelocatable(Value, Asm, Fixup);
75 
76   if (!isRelocatable)
77     return false;
78 
79   if (Value.isAbsolute()) {
80     Result = MCValue::get(evaluateAsInt64(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(&Sym->getSymbol(), Modifier, Context);
95     Result = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
96   }
97 
98   return true;
99 }
100 
evaluateAsInt64(int64_t Value) const101 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 
getFixupKind() const148 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 
visitUsedExpr(MCStreamer & Streamer) const192 void AVRMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
193   Streamer.visitUsedExpr(*getSubExpr());
194 }
195 
getName() const196 const char *AVRMCExpr::getName() const {
197   const auto &Modifier =
198       llvm::find_if(ModifierNames, [this](ModifierEntry const &Mod) {
199         return Mod.VariantKind == Kind;
200       });
201 
202   if (Modifier != std::end(ModifierNames)) {
203     return Modifier->Spelling;
204   }
205   return nullptr;
206 }
207 
getKindByName(StringRef Name)208 AVRMCExpr::VariantKind AVRMCExpr::getKindByName(StringRef Name) {
209   const auto &Modifier =
210       llvm::find_if(ModifierNames, [&Name](ModifierEntry const &Mod) {
211         return Mod.Spelling == Name;
212       });
213 
214   if (Modifier != std::end(ModifierNames)) {
215     return Modifier->VariantKind;
216   }
217   return VK_AVR_None;
218 }
219 
220 } // end of namespace llvm
221