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