blob: 400296b8409b49c6718496d920b5c3567fc60830 [file] [log] [blame]
Dylan McKayc4ec11f2016-09-26 11:35:32 +00001//===-- 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
18namespace llvm {
19
20namespace {
21
22const 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
36const AVRMCExpr *AVRMCExpr::create(VariantKind Kind, const MCExpr *Expr,
37 bool Negated, MCContext &Ctx) {
38 return new (Ctx) AVRMCExpr(Kind, Expr, Negated);
39}
40
41void 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
52bool 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
69bool 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
96int64_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
128AVR::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
162void AVRMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
163 Streamer.visitUsedExpr(*getSubExpr());
164}
165
166const 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
177AVRMCExpr::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