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