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