1//===-- AVRMCAsmInfo.cpp - AVR asm properties -----------------------------===//
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// This file contains the declarations of the AVRMCAsmInfo properties.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AVRMCAsmInfo.h"
14#include "llvm/MC/MCAssembler.h"
15#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCValue.h"
18#include "llvm/TargetParser/Triple.h"
19
20using namespace llvm;
21
22AVRMCAsmInfo::AVRMCAsmInfo(const Triple &TT, const MCTargetOptions &Options)
23 : MCAsmInfoELF(Options) {
24 CodePointerSize = 2;
25 CalleeSaveStackSlotSize = 2;
26 CommentString = ";";
27 SeparatorString = "$";
28 UsesELFSectionDirectiveForBSS = true;
29 SupportsDebugInformation = true;
30}
31
32namespace {
33const struct ModifierEntry {
34 const char *const Spelling;
35 AVRMCExpr::Specifier specifier;
36} ModifierNames[] = {
37 {.Spelling: "lo8", .specifier: AVR::S_LO8}, {.Spelling: "hi8", .specifier: AVR::S_HI8},
38 {.Spelling: "hh8", .specifier: AVR::S_HH8}, // synonym with hlo8
39 {.Spelling: "hlo8", .specifier: AVR::S_HH8}, {.Spelling: "hhi8", .specifier: AVR::S_HHI8},
40
41 {.Spelling: "pm", .specifier: AVR::S_PM}, {.Spelling: "pm_lo8", .specifier: AVR::S_PM_LO8},
42 {.Spelling: "pm_hi8", .specifier: AVR::S_PM_HI8}, {.Spelling: "pm_hh8", .specifier: AVR::S_PM_HH8},
43
44 {.Spelling: "lo8_gs", .specifier: AVR::S_LO8_GS}, {.Spelling: "hi8_gs", .specifier: AVR::S_HI8_GS},
45 {.Spelling: "gs", .specifier: AVR::S_GS},
46};
47
48} // end of anonymous namespace
49
50AVRMCExpr::Specifier AVRMCExpr::parseSpecifier(StringRef Name) {
51 const auto &Modifier =
52 llvm::find_if(Range: ModifierNames, P: [&Name](ModifierEntry const &Mod) {
53 return Mod.Spelling == Name;
54 });
55
56 if (Modifier != std::end(arr: ModifierNames)) {
57 return Modifier->specifier;
58 }
59 return AVR::S_AVR_NONE;
60}
61
62const char *AVRMCExpr::getName() const {
63 const auto &Modifier =
64 llvm::find_if(Range: ModifierNames, P: [this](ModifierEntry const &Mod) {
65 return Mod.specifier == getSpecifier();
66 });
67
68 if (Modifier != std::end(arr: ModifierNames)) {
69 return Modifier->Spelling;
70 }
71 return nullptr;
72}
73
74AVR::Fixups AVRMCExpr::getFixupKind() const {
75 AVR::Fixups Kind = AVR::Fixups::LastTargetFixupKind;
76
77 switch (getSpecifier()) {
78 case AVR::S_LO8:
79 Kind = isNegated() ? AVR::fixup_lo8_ldi_neg : AVR::fixup_lo8_ldi;
80 break;
81 case AVR::S_HI8:
82 Kind = isNegated() ? AVR::fixup_hi8_ldi_neg : AVR::fixup_hi8_ldi;
83 break;
84 case AVR::S_HH8:
85 Kind = isNegated() ? AVR::fixup_hh8_ldi_neg : AVR::fixup_hh8_ldi;
86 break;
87 case AVR::S_HHI8:
88 Kind = isNegated() ? AVR::fixup_ms8_ldi_neg : AVR::fixup_ms8_ldi;
89 break;
90
91 case AVR::S_PM_LO8:
92 Kind = isNegated() ? AVR::fixup_lo8_ldi_pm_neg : AVR::fixup_lo8_ldi_pm;
93 break;
94 case AVR::S_PM_HI8:
95 Kind = isNegated() ? AVR::fixup_hi8_ldi_pm_neg : AVR::fixup_hi8_ldi_pm;
96 break;
97 case AVR::S_PM_HH8:
98 Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm;
99 break;
100 case AVR::S_PM:
101 case AVR::S_GS:
102 Kind = AVR::fixup_16_pm;
103 break;
104 case AVR::S_LO8_GS:
105 Kind = AVR::fixup_lo8_ldi_gs;
106 break;
107 case AVR::S_HI8_GS:
108 Kind = AVR::fixup_hi8_ldi_gs;
109 break;
110
111 default:
112 llvm_unreachable("Uninitialized expression");
113 }
114
115 return Kind;
116}
117
118void AVRMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
119 const MCSpecifierExpr &Expr) const {
120 auto &E = static_cast<const AVRMCExpr &>(Expr);
121 assert(E.getSpecifier() != AVR::S_AVR_NONE);
122 OS << E.getName() << '(';
123 if (E.isNegated())
124 OS << '-' << '(';
125 printExpr(OS, *E.getSubExpr());
126 if (E.isNegated())
127 OS << ')';
128 OS << ')';
129}
130
131int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const {
132 if (Negated)
133 Value *= -1;
134
135 switch (getSpecifier()) {
136 case AVR::S_LO8:
137 Value &= 0xff;
138 break;
139 case AVR::S_HI8:
140 Value &= 0xff00;
141 Value >>= 8;
142 break;
143 case AVR::S_HH8:
144 Value &= 0xff0000;
145 Value >>= 16;
146 break;
147 case AVR::S_HHI8:
148 Value &= 0xff000000;
149 Value >>= 24;
150 break;
151 case AVR::S_PM_LO8:
152 case AVR::S_LO8_GS:
153 Value >>= 1; // Program memory addresses must always be shifted by one.
154 Value &= 0xff;
155 break;
156 case AVR::S_PM_HI8:
157 case AVR::S_HI8_GS:
158 Value >>= 1; // Program memory addresses must always be shifted by one.
159 Value &= 0xff00;
160 Value >>= 8;
161 break;
162 case AVR::S_PM_HH8:
163 Value >>= 1; // Program memory addresses must always be shifted by one.
164 Value &= 0xff0000;
165 Value >>= 16;
166 break;
167 case AVR::S_PM:
168 case AVR::S_GS:
169 Value >>= 1; // Program memory addresses must always be shifted by one.
170 break;
171
172 case AVR::S_AVR_NONE:
173 default:
174 llvm_unreachable("Uninitialized expression.");
175 }
176 return static_cast<uint64_t>(Value) & 0xff;
177}
178
179// bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result,
180// const MCAssembler *Asm) const {
181bool AVRMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr,
182 MCValue &Result,
183 const MCAssembler *Asm) const {
184 auto &E = static_cast<const AVRMCExpr &>(Expr);
185 MCValue Value;
186 bool isRelocatable = E.getSubExpr()->evaluateAsRelocatable(Res&: Value, Asm);
187 if (!isRelocatable)
188 return false;
189
190 if (Value.isAbsolute()) {
191 Result = MCValue::get(Val: E.evaluateAsInt64(Value: Value.getConstant()));
192 } else {
193 if (!Asm || !Asm->hasLayout())
194 return false;
195
196 auto Spec = AVR::S_None;
197 if (Value.getSpecifier())
198 return false;
199 assert(!Value.getSubSym());
200 if (E.getSpecifier() == AVR::S_PM)
201 Spec = AVR::S_PM;
202
203 // TODO: don't attach specifier to MCSymbolRefExpr.
204 Result =
205 MCValue::get(SymA: Value.getAddSym(), SymB: nullptr, Val: Value.getConstant(), Specifier: Spec);
206 }
207
208 return true;
209}
210
211bool AVRMCExpr::evaluateAsConstant(int64_t &Result) const {
212 MCValue Value;
213 bool isRelocatable = getSubExpr()->evaluateAsRelocatable(Res&: Value, Asm: nullptr);
214 if (!isRelocatable)
215 return false;
216
217 if (Value.isAbsolute()) {
218 Result = evaluateAsInt64(Value: Value.getConstant());
219 return true;
220 }
221
222 return false;
223}
224