1 //===-- AVRMCExpr.cpp - AVR specific MC expression classes ----------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "llvm/MC/MCAssembler.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCStreamer.h"
14 #include "llvm/MC/MCValue.h"
20 const struct ModifierEntry
{
21 const char *const Spelling
;
22 AVRMCExpr::VariantKind VariantKind
;
24 {"lo8", AVRMCExpr::VK_AVR_LO8
}, {"hi8", AVRMCExpr::VK_AVR_HI8
},
25 {"hh8", AVRMCExpr::VK_AVR_HH8
}, // synonym with hlo8
26 {"hlo8", AVRMCExpr::VK_AVR_HH8
}, {"hhi8", AVRMCExpr::VK_AVR_HHI8
},
28 {"pm", AVRMCExpr::VK_AVR_PM
}, {"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8
},
29 {"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8
}, {"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8
},
31 {"lo8_gs", AVRMCExpr::VK_AVR_LO8_GS
}, {"hi8_gs", AVRMCExpr::VK_AVR_HI8_GS
},
32 {"gs", AVRMCExpr::VK_AVR_GS
},
35 } // end of anonymous namespace
37 const AVRMCExpr
*AVRMCExpr::create(VariantKind Kind
, const MCExpr
*Expr
,
38 bool Negated
, MCContext
&Ctx
) {
39 return new (Ctx
) AVRMCExpr(Kind
, Expr
, Negated
);
42 void AVRMCExpr::printImpl(raw_ostream
&OS
, const MCAsmInfo
*MAI
) const {
43 assert(Kind
!= VK_AVR_None
);
44 OS
<< getName() << '(';
47 getSubExpr()->print(OS
, MAI
);
53 bool AVRMCExpr::evaluateAsConstant(int64_t &Result
) const {
57 getSubExpr()->evaluateAsRelocatable(Value
, nullptr, nullptr);
62 if (Value
.isAbsolute()) {
63 Result
= evaluateAsInt64(Value
.getConstant());
70 bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue
&Result
,
71 const MCAssembler
*Asm
,
72 const MCFixup
*Fixup
) const {
74 bool isRelocatable
= SubExpr
->evaluateAsRelocatable(Value
, Asm
, Fixup
);
79 if (Value
.isAbsolute()) {
80 Result
= MCValue::get(evaluateAsInt64(Value
.getConstant()));
82 if (!Asm
|| !Asm
->hasLayout())
85 MCContext
&Context
= Asm
->getContext();
86 const MCSymbolRefExpr
*Sym
= Value
.getSymA();
87 MCSymbolRefExpr::VariantKind Modifier
= Sym
->getKind();
88 if (Modifier
!= MCSymbolRefExpr::VK_None
)
90 if (Kind
== VK_AVR_PM
) {
91 Modifier
= MCSymbolRefExpr::VK_AVR_PM
;
94 Sym
= MCSymbolRefExpr::create(&Sym
->getSymbol(), Modifier
, Context
);
95 Result
= MCValue::get(Sym
, Value
.getSymB(), Value
.getConstant());
101 int64_t AVRMCExpr::evaluateAsInt64(int64_t Value
) const {
106 case AVRMCExpr::VK_AVR_LO8
:
109 case AVRMCExpr::VK_AVR_HI8
:
113 case AVRMCExpr::VK_AVR_HH8
:
117 case AVRMCExpr::VK_AVR_HHI8
:
121 case AVRMCExpr::VK_AVR_PM_LO8
:
122 case AVRMCExpr::VK_AVR_LO8_GS
:
123 Value
>>= 1; // Program memory addresses must always be shifted by one.
126 case AVRMCExpr::VK_AVR_PM_HI8
:
127 case AVRMCExpr::VK_AVR_HI8_GS
:
128 Value
>>= 1; // Program memory addresses must always be shifted by one.
132 case AVRMCExpr::VK_AVR_PM_HH8
:
133 Value
>>= 1; // Program memory addresses must always be shifted by one.
137 case AVRMCExpr::VK_AVR_PM
:
138 case AVRMCExpr::VK_AVR_GS
:
139 Value
>>= 1; // Program memory addresses must always be shifted by one.
142 case AVRMCExpr::VK_AVR_None
:
143 llvm_unreachable("Uninitialized expression.");
145 return static_cast<uint64_t>(Value
) & 0xff;
148 AVR::Fixups
AVRMCExpr::getFixupKind() const {
149 AVR::Fixups Kind
= AVR::Fixups::LastTargetFixupKind
;
153 Kind
= isNegated() ? AVR::fixup_lo8_ldi_neg
: AVR::fixup_lo8_ldi
;
156 Kind
= isNegated() ? AVR::fixup_hi8_ldi_neg
: AVR::fixup_hi8_ldi
;
159 Kind
= isNegated() ? AVR::fixup_hh8_ldi_neg
: AVR::fixup_hh8_ldi
;
162 Kind
= isNegated() ? AVR::fixup_ms8_ldi_neg
: AVR::fixup_ms8_ldi
;
166 Kind
= isNegated() ? AVR::fixup_lo8_ldi_pm_neg
: AVR::fixup_lo8_ldi_pm
;
169 Kind
= isNegated() ? AVR::fixup_hi8_ldi_pm_neg
: AVR::fixup_hi8_ldi_pm
;
172 Kind
= isNegated() ? AVR::fixup_hh8_ldi_pm_neg
: AVR::fixup_hh8_ldi_pm
;
176 Kind
= AVR::fixup_16_pm
;
179 Kind
= AVR::fixup_lo8_ldi_gs
;
182 Kind
= AVR::fixup_hi8_ldi_gs
;
186 llvm_unreachable("Uninitialized expression");
192 void AVRMCExpr::visitUsedExpr(MCStreamer
&Streamer
) const {
193 Streamer
.visitUsedExpr(*getSubExpr());
196 const char *AVRMCExpr::getName() const {
197 const auto &Modifier
=
198 llvm::find_if(ModifierNames
, [this](ModifierEntry
const &Mod
) {
199 return Mod
.VariantKind
== Kind
;
202 if (Modifier
!= std::end(ModifierNames
)) {
203 return Modifier
->Spelling
;
208 AVRMCExpr::VariantKind
AVRMCExpr::getKindByName(StringRef Name
) {
209 const auto &Modifier
=
210 llvm::find_if(ModifierNames
, [&Name
](ModifierEntry
const &Mod
) {
211 return Mod
.Spelling
== Name
;
214 if (Modifier
!= std::end(ModifierNames
)) {
215 return Modifier
->VariantKind
;
220 } // end of namespace llvm