1 //===-- AVRMCExpr.cpp - AVR specific MC expression classes ----------------===// 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 #include "AVRMCExpr.h" 10 11 #include "llvm/MC/MCAsmLayout.h" 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 17 namespace llvm { 18 19 namespace { 20 21 const struct ModifierEntry { 22 const char * const Spelling; 23 AVRMCExpr::VariantKind VariantKind; 24 } ModifierNames[] = { 25 {"lo8", AVRMCExpr::VK_AVR_LO8}, {"hi8", AVRMCExpr::VK_AVR_HI8}, 26 {"hh8", AVRMCExpr::VK_AVR_HH8}, // synonym with hlo8 27 {"hlo8", AVRMCExpr::VK_AVR_HH8}, {"hhi8", AVRMCExpr::VK_AVR_HHI8}, 28 29 {"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8}, {"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8}, 30 {"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8}, 31 32 {"lo8_gs", AVRMCExpr::VK_AVR_LO8_GS}, {"hi8_gs", AVRMCExpr::VK_AVR_HI8_GS}, 33 {"gs", AVRMCExpr::VK_AVR_GS}, 34 }; 35 36 } // end of anonymous namespace 37 38 const AVRMCExpr *AVRMCExpr::create(VariantKind Kind, const MCExpr *Expr, 39 bool Negated, MCContext &Ctx) { 40 return new (Ctx) AVRMCExpr(Kind, Expr, Negated); 41 } 42 43 void AVRMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 44 assert(Kind != VK_AVR_None); 45 46 if (isNegated()) 47 OS << '-'; 48 49 OS << getName() << '('; 50 getSubExpr()->print(OS, MAI); 51 OS << ')'; 52 } 53 54 bool AVRMCExpr::evaluateAsConstant(int64_t &Result) const { 55 MCValue Value; 56 57 bool isRelocatable = 58 getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr); 59 60 if (!isRelocatable) 61 return false; 62 63 if (Value.isAbsolute()) { 64 Result = evaluateAsInt64(Value.getConstant()); 65 return true; 66 } 67 68 return false; 69 } 70 71 bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result, 72 const MCAsmLayout *Layout, 73 const MCFixup *Fixup) const { 74 MCValue Value; 75 bool isRelocatable = SubExpr->evaluateAsRelocatable(Value, Layout, Fixup); 76 77 if (!isRelocatable) 78 return false; 79 80 if (Value.isAbsolute()) { 81 Result = MCValue::get(evaluateAsInt64(Value.getConstant())); 82 } else { 83 if (!Layout) return false; 84 85 MCContext &Context = Layout->getAssembler().getContext(); 86 const MCSymbolRefExpr *Sym = Value.getSymA(); 87 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind(); 88 if (Modifier != MCSymbolRefExpr::VK_None) 89 return false; 90 91 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context); 92 Result = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); 93 } 94 95 return true; 96 } 97 98 int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const { 99 if (Negated) 100 Value *= -1; 101 102 switch (Kind) { 103 case AVRMCExpr::VK_AVR_LO8: 104 Value &= 0xff; 105 break; 106 case AVRMCExpr::VK_AVR_HI8: 107 Value &= 0xff00; 108 Value >>= 8; 109 break; 110 case AVRMCExpr::VK_AVR_HH8: 111 Value &= 0xff0000; 112 Value >>= 16; 113 break; 114 case AVRMCExpr::VK_AVR_HHI8: 115 Value &= 0xff000000; 116 Value >>= 24; 117 break; 118 case AVRMCExpr::VK_AVR_PM_LO8: 119 case AVRMCExpr::VK_AVR_LO8_GS: 120 Value >>= 1; // Program memory addresses must always be shifted by one. 121 Value &= 0xff; 122 break; 123 case AVRMCExpr::VK_AVR_PM_HI8: 124 case AVRMCExpr::VK_AVR_HI8_GS: 125 Value >>= 1; // Program memory addresses must always be shifted by one. 126 Value &= 0xff00; 127 Value >>= 8; 128 break; 129 case AVRMCExpr::VK_AVR_PM_HH8: 130 Value >>= 1; // Program memory addresses must always be shifted by one. 131 Value &= 0xff0000; 132 Value >>= 16; 133 break; 134 case AVRMCExpr::VK_AVR_GS: 135 Value >>= 1; // Program memory addresses must always be shifted by one. 136 break; 137 138 case AVRMCExpr::VK_AVR_None: 139 llvm_unreachable("Uninitialized expression."); 140 } 141 return static_cast<uint64_t>(Value) & 0xff; 142 } 143 144 AVR::Fixups AVRMCExpr::getFixupKind() const { 145 AVR::Fixups Kind = AVR::Fixups::LastTargetFixupKind; 146 147 switch (getKind()) { 148 case VK_AVR_LO8: 149 Kind = isNegated() ? AVR::fixup_lo8_ldi_neg : AVR::fixup_lo8_ldi; 150 break; 151 case VK_AVR_HI8: 152 Kind = isNegated() ? AVR::fixup_hi8_ldi_neg : AVR::fixup_hi8_ldi; 153 break; 154 case VK_AVR_HH8: 155 Kind = isNegated() ? AVR::fixup_hh8_ldi_neg : AVR::fixup_hh8_ldi; 156 break; 157 case VK_AVR_HHI8: 158 Kind = isNegated() ? AVR::fixup_ms8_ldi_neg : AVR::fixup_ms8_ldi; 159 break; 160 161 case VK_AVR_PM_LO8: 162 Kind = isNegated() ? AVR::fixup_lo8_ldi_pm_neg : AVR::fixup_lo8_ldi_pm; 163 break; 164 case VK_AVR_PM_HI8: 165 Kind = isNegated() ? AVR::fixup_hi8_ldi_pm_neg : AVR::fixup_hi8_ldi_pm; 166 break; 167 case VK_AVR_PM_HH8: 168 Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm; 169 break; 170 case VK_AVR_GS: 171 Kind = AVR::fixup_16_pm; 172 break; 173 case VK_AVR_LO8_GS: 174 Kind = AVR::fixup_lo8_ldi_gs; 175 break; 176 case VK_AVR_HI8_GS: 177 Kind = AVR::fixup_hi8_ldi_gs; 178 break; 179 180 case VK_AVR_None: 181 llvm_unreachable("Uninitialized expression"); 182 } 183 184 return Kind; 185 } 186 187 void AVRMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 188 Streamer.visitUsedExpr(*getSubExpr()); 189 } 190 191 const char *AVRMCExpr::getName() const { 192 const auto &Modifier = std::find_if( 193 std::begin(ModifierNames), std::end(ModifierNames), 194 [this](ModifierEntry const &Mod) { return Mod.VariantKind == Kind; }); 195 196 if (Modifier != std::end(ModifierNames)) { 197 return Modifier->Spelling; 198 } 199 return nullptr; 200 } 201 202 AVRMCExpr::VariantKind AVRMCExpr::getKindByName(StringRef Name) { 203 const auto &Modifier = std::find_if( 204 std::begin(ModifierNames), std::end(ModifierNames), 205 [&Name](ModifierEntry const &Mod) { return Mod.Spelling == Name; }); 206 207 if (Modifier != std::end(ModifierNames)) { 208 return Modifier->VariantKind; 209 } 210 return VK_AVR_None; 211 } 212 213 } // end of namespace llvm 214 215