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