• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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