10b57cec5SDimitry Andric //===-- AVRAsmBackend.cpp - AVR Asm Backend ------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the AVRAsmBackend class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MCTargetDesc/AVRAsmBackend.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/AVRFixupKinds.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h" 160fca6ea1SDimitry Andric #include "llvm/ADT/StringSwitch.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h" 22e8d8bef9SDimitry Andric #include "llvm/MC/MCExpr.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 280b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric // FIXME: we should be doing checks to make sure asm operands 320b57cec5SDimitry Andric // are not out of bounds. 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric namespace adjust { 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric 385ffd83dbSDimitry Andric static void signed_width(unsigned Width, uint64_t Value, 395ffd83dbSDimitry Andric std::string Description, const MCFixup &Fixup, 405ffd83dbSDimitry Andric MCContext *Ctx = nullptr) { 410b57cec5SDimitry Andric if (!isIntN(Width, Value)) { 420b57cec5SDimitry Andric std::string Diagnostic = "out of range " + Description; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric int64_t Min = minIntN(Width); 450b57cec5SDimitry Andric int64_t Max = maxIntN(Width); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric Diagnostic += " (expected an integer in the range " + std::to_string(Min) + 480b57cec5SDimitry Andric " to " + std::to_string(Max) + ")"; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric if (Ctx) { 5104eeddc0SDimitry Andric Ctx->reportError(Fixup.getLoc(), Diagnostic); 520b57cec5SDimitry Andric } else { 530b57cec5SDimitry Andric llvm_unreachable(Diagnostic.c_str()); 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 585ffd83dbSDimitry Andric static void unsigned_width(unsigned Width, uint64_t Value, 595ffd83dbSDimitry Andric std::string Description, const MCFixup &Fixup, 605ffd83dbSDimitry Andric MCContext *Ctx = nullptr) { 610b57cec5SDimitry Andric if (!isUIntN(Width, Value)) { 620b57cec5SDimitry Andric std::string Diagnostic = "out of range " + Description; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric int64_t Max = maxUIntN(Width); 650b57cec5SDimitry Andric 66349cc55cSDimitry Andric Diagnostic += 67349cc55cSDimitry Andric " (expected an integer in the range 0 to " + std::to_string(Max) + ")"; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric if (Ctx) { 7004eeddc0SDimitry Andric Ctx->reportError(Fixup.getLoc(), Diagnostic); 710b57cec5SDimitry Andric } else { 720b57cec5SDimitry Andric llvm_unreachable(Diagnostic.c_str()); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric /// Adjusts the value of a branch target before fixup application. 785ffd83dbSDimitry Andric static void adjustBranch(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 790b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 800b57cec5SDimitry Andric // We have one extra bit of precision because the value is rightshifted by 810b57cec5SDimitry Andric // one. 820b57cec5SDimitry Andric unsigned_width(Size + 1, Value, std::string("branch target"), Fixup, Ctx); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric // Rightshifts the value by one. 850b57cec5SDimitry Andric AVR::fixups::adjustBranchTarget(Value); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric /// Adjusts the value of a relative branch target before fixup application. 895ffd83dbSDimitry Andric static void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup, 905ffd83dbSDimitry Andric uint64_t &Value, MCContext *Ctx = nullptr) { 91*d686ce93SDimitry Andric // Jumps are relative to the current instruction. 92*d686ce93SDimitry Andric Value -= 2; 93*d686ce93SDimitry Andric 940b57cec5SDimitry Andric // We have one extra bit of precision because the value is rightshifted by 950b57cec5SDimitry Andric // one. 960b57cec5SDimitry Andric signed_width(Size + 1, Value, std::string("branch target"), Fixup, Ctx); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric // Rightshifts the value by one. 990b57cec5SDimitry Andric AVR::fixups::adjustBranchTarget(Value); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric /// 22-bit absolute fixup. 1030b57cec5SDimitry Andric /// 1040b57cec5SDimitry Andric /// Resolves to: 1050b57cec5SDimitry Andric /// 1001 kkkk 010k kkkk kkkk kkkk 111k kkkk 1060b57cec5SDimitry Andric /// 1070b57cec5SDimitry Andric /// Offset of 0 (so the result is left shifted by 3 bits before application). 1085ffd83dbSDimitry Andric static void fixup_call(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 1090b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 1100b57cec5SDimitry Andric adjustBranch(Size, Fixup, Value, Ctx); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric auto top = Value & (0xf00000 << 6); // the top four bits 1130b57cec5SDimitry Andric auto middle = Value & (0x1ffff << 5); // the middle 13 bits 1140b57cec5SDimitry Andric auto bottom = Value & 0x1f; // end bottom 5 bits 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric Value = (top << 6) | (middle << 3) | (bottom << 0); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric /// 7-bit PC-relative fixup. 1200b57cec5SDimitry Andric /// 1210b57cec5SDimitry Andric /// Resolves to: 1220b57cec5SDimitry Andric /// 0000 00kk kkkk k000 1230b57cec5SDimitry Andric /// Offset of 0 (so the result is left shifted by 3 bits before application). 1245ffd83dbSDimitry Andric static void fixup_7_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 1250b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 1260b57cec5SDimitry Andric adjustRelativeBranch(Size, Fixup, Value, Ctx); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric // Because the value may be negative, we must mask out the sign bits 1290b57cec5SDimitry Andric Value &= 0x7f; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric /// 12-bit PC-relative fixup. 1330b57cec5SDimitry Andric /// Yes, the fixup is 12 bits even though the name says otherwise. 1340b57cec5SDimitry Andric /// 1350b57cec5SDimitry Andric /// Resolves to: 1360b57cec5SDimitry Andric /// 0000 kkkk kkkk kkkk 1370b57cec5SDimitry Andric /// Offset of 0 (so the result isn't left-shifted before application). 1385ffd83dbSDimitry Andric static void fixup_13_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 1390b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 1400b57cec5SDimitry Andric adjustRelativeBranch(Size, Fixup, Value, Ctx); 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // Because the value may be negative, we must mask out the sign bits 1430b57cec5SDimitry Andric Value &= 0xfff; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1465ffd83dbSDimitry Andric /// 6-bit fixup for the immediate operand of the STD/LDD family of 1475ffd83dbSDimitry Andric /// instructions. 1485ffd83dbSDimitry Andric /// 1495ffd83dbSDimitry Andric /// Resolves to: 1505ffd83dbSDimitry Andric /// 10q0 qq10 0000 1qqq 1515ffd83dbSDimitry Andric static void fixup_6(const MCFixup &Fixup, uint64_t &Value, 1525ffd83dbSDimitry Andric MCContext *Ctx = nullptr) { 1535ffd83dbSDimitry Andric unsigned_width(6, Value, std::string("immediate"), Fixup, Ctx); 1545ffd83dbSDimitry Andric 1555ffd83dbSDimitry Andric Value = ((Value & 0x20) << 8) | ((Value & 0x18) << 7) | (Value & 0x07); 1565ffd83dbSDimitry Andric } 1575ffd83dbSDimitry Andric 1580b57cec5SDimitry Andric /// 6-bit fixup for the immediate operand of the ADIW family of 1590b57cec5SDimitry Andric /// instructions. 1600b57cec5SDimitry Andric /// 1610b57cec5SDimitry Andric /// Resolves to: 1620b57cec5SDimitry Andric /// 0000 0000 kk00 kkkk 1635ffd83dbSDimitry Andric static void fixup_6_adiw(const MCFixup &Fixup, uint64_t &Value, 1640b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 1650b57cec5SDimitry Andric unsigned_width(6, Value, std::string("immediate"), Fixup, Ctx); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric Value = ((Value & 0x30) << 2) | (Value & 0x0f); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric /// 5-bit port number fixup on the SBIC family of instructions. 1710b57cec5SDimitry Andric /// 1720b57cec5SDimitry Andric /// Resolves to: 1730b57cec5SDimitry Andric /// 0000 0000 AAAA A000 1745ffd83dbSDimitry Andric static void fixup_port5(const MCFixup &Fixup, uint64_t &Value, 1750b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 1760b57cec5SDimitry Andric unsigned_width(5, Value, std::string("port number"), Fixup, Ctx); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric Value &= 0x1f; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric Value <<= 3; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric /// 6-bit port number fixup on the `IN` family of instructions. 1840b57cec5SDimitry Andric /// 1850b57cec5SDimitry Andric /// Resolves to: 1860b57cec5SDimitry Andric /// 1011 0AAd dddd AAAA 1875ffd83dbSDimitry Andric static void fixup_port6(const MCFixup &Fixup, uint64_t &Value, 1880b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 1890b57cec5SDimitry Andric unsigned_width(6, Value, std::string("port number"), Fixup, Ctx); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric Value = ((Value & 0x30) << 5) | (Value & 0x0f); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 194bdd1243dSDimitry Andric /// 7-bit data space address fixup for the LDS/STS instructions on AVRTiny. 195bdd1243dSDimitry Andric /// 196bdd1243dSDimitry Andric /// Resolves to: 197bdd1243dSDimitry Andric /// 1010 ikkk dddd kkkk 198bdd1243dSDimitry Andric static void fixup_lds_sts_16(const MCFixup &Fixup, uint64_t &Value, 199bdd1243dSDimitry Andric MCContext *Ctx = nullptr) { 200bdd1243dSDimitry Andric unsigned_width(7, Value, std::string("immediate"), Fixup, Ctx); 201bdd1243dSDimitry Andric Value = ((Value & 0x70) << 8) | (Value & 0x0f); 202bdd1243dSDimitry Andric } 203bdd1243dSDimitry Andric 2040b57cec5SDimitry Andric /// Adjusts a program memory address. 2050b57cec5SDimitry Andric /// This is a simple right-shift. 2065ffd83dbSDimitry Andric static void pm(uint64_t &Value) { Value >>= 1; } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric /// Fixups relating to the LDI instruction. 2090b57cec5SDimitry Andric namespace ldi { 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric /// Adjusts a value to fix up the immediate of an `LDI Rd, K` instruction. 2120b57cec5SDimitry Andric /// 2130b57cec5SDimitry Andric /// Resolves to: 2140b57cec5SDimitry Andric /// 0000 KKKK 0000 KKKK 2150b57cec5SDimitry Andric /// Offset of 0 (so the result isn't left-shifted before application). 2165ffd83dbSDimitry Andric static void fixup(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 2170b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 2180b57cec5SDimitry Andric uint64_t upper = Value & 0xf0; 2190b57cec5SDimitry Andric uint64_t lower = Value & 0x0f; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric Value = (upper << 4) | lower; 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2245ffd83dbSDimitry Andric static void neg(uint64_t &Value) { Value *= -1; } 2250b57cec5SDimitry Andric 2265ffd83dbSDimitry Andric static void lo8(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 2270b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 2280b57cec5SDimitry Andric Value &= 0xff; 2290b57cec5SDimitry Andric ldi::fixup(Size, Fixup, Value, Ctx); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2325ffd83dbSDimitry Andric static void hi8(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 2330b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 2340b57cec5SDimitry Andric Value = (Value & 0xff00) >> 8; 2350b57cec5SDimitry Andric ldi::fixup(Size, Fixup, Value, Ctx); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2385ffd83dbSDimitry Andric static void hh8(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 2390b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 2400b57cec5SDimitry Andric Value = (Value & 0xff0000) >> 16; 2410b57cec5SDimitry Andric ldi::fixup(Size, Fixup, Value, Ctx); 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2445ffd83dbSDimitry Andric static void ms8(unsigned Size, const MCFixup &Fixup, uint64_t &Value, 2450b57cec5SDimitry Andric MCContext *Ctx = nullptr) { 2460b57cec5SDimitry Andric Value = (Value & 0xff000000) >> 24; 2470b57cec5SDimitry Andric ldi::fixup(Size, Fixup, Value, Ctx); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 250349cc55cSDimitry Andric } // namespace ldi 251349cc55cSDimitry Andric } // namespace adjust 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric namespace llvm { 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric // Prepare value for the target space for it 2560b57cec5SDimitry Andric void AVRAsmBackend::adjustFixupValue(const MCFixup &Fixup, 257349cc55cSDimitry Andric const MCValue &Target, uint64_t &Value, 2580b57cec5SDimitry Andric MCContext *Ctx) const { 2590b57cec5SDimitry Andric // The size of the fixup in bits. 2600b57cec5SDimitry Andric uint64_t Size = AVRAsmBackend::getFixupKindInfo(Fixup.getKind()).TargetSize; 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric unsigned Kind = Fixup.getKind(); 2630b57cec5SDimitry Andric switch (Kind) { 2640b57cec5SDimitry Andric default: 2650b57cec5SDimitry Andric llvm_unreachable("unhandled fixup"); 2660b57cec5SDimitry Andric case AVR::fixup_7_pcrel: 2670b57cec5SDimitry Andric adjust::fixup_7_pcrel(Size, Fixup, Value, Ctx); 2680b57cec5SDimitry Andric break; 2690b57cec5SDimitry Andric case AVR::fixup_13_pcrel: 2700b57cec5SDimitry Andric adjust::fixup_13_pcrel(Size, Fixup, Value, Ctx); 2710b57cec5SDimitry Andric break; 2720b57cec5SDimitry Andric case AVR::fixup_call: 2730b57cec5SDimitry Andric adjust::fixup_call(Size, Fixup, Value, Ctx); 2740b57cec5SDimitry Andric break; 2750b57cec5SDimitry Andric case AVR::fixup_ldi: 2760b57cec5SDimitry Andric adjust::ldi::fixup(Size, Fixup, Value, Ctx); 2770b57cec5SDimitry Andric break; 2780b57cec5SDimitry Andric case AVR::fixup_lo8_ldi: 2790b57cec5SDimitry Andric adjust::ldi::lo8(Size, Fixup, Value, Ctx); 2800b57cec5SDimitry Andric break; 2810b57cec5SDimitry Andric case AVR::fixup_lo8_ldi_pm: 2820b57cec5SDimitry Andric case AVR::fixup_lo8_ldi_gs: 2830b57cec5SDimitry Andric adjust::pm(Value); 2840b57cec5SDimitry Andric adjust::ldi::lo8(Size, Fixup, Value, Ctx); 2850b57cec5SDimitry Andric break; 2860b57cec5SDimitry Andric case AVR::fixup_hi8_ldi: 2870b57cec5SDimitry Andric adjust::ldi::hi8(Size, Fixup, Value, Ctx); 2880b57cec5SDimitry Andric break; 2890b57cec5SDimitry Andric case AVR::fixup_hi8_ldi_pm: 2900b57cec5SDimitry Andric case AVR::fixup_hi8_ldi_gs: 2910b57cec5SDimitry Andric adjust::pm(Value); 2920b57cec5SDimitry Andric adjust::ldi::hi8(Size, Fixup, Value, Ctx); 2930b57cec5SDimitry Andric break; 2940b57cec5SDimitry Andric case AVR::fixup_hh8_ldi: 2950b57cec5SDimitry Andric case AVR::fixup_hh8_ldi_pm: 296349cc55cSDimitry Andric if (Kind == AVR::fixup_hh8_ldi_pm) 297349cc55cSDimitry Andric adjust::pm(Value); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric adjust::ldi::hh8(Size, Fixup, Value, Ctx); 3000b57cec5SDimitry Andric break; 3010b57cec5SDimitry Andric case AVR::fixup_ms8_ldi: 3020b57cec5SDimitry Andric adjust::ldi::ms8(Size, Fixup, Value, Ctx); 3030b57cec5SDimitry Andric break; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric case AVR::fixup_lo8_ldi_neg: 3060b57cec5SDimitry Andric case AVR::fixup_lo8_ldi_pm_neg: 307349cc55cSDimitry Andric if (Kind == AVR::fixup_lo8_ldi_pm_neg) 308349cc55cSDimitry Andric adjust::pm(Value); 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric adjust::ldi::neg(Value); 3110b57cec5SDimitry Andric adjust::ldi::lo8(Size, Fixup, Value, Ctx); 3120b57cec5SDimitry Andric break; 3130b57cec5SDimitry Andric case AVR::fixup_hi8_ldi_neg: 3140b57cec5SDimitry Andric case AVR::fixup_hi8_ldi_pm_neg: 315349cc55cSDimitry Andric if (Kind == AVR::fixup_hi8_ldi_pm_neg) 316349cc55cSDimitry Andric adjust::pm(Value); 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric adjust::ldi::neg(Value); 3190b57cec5SDimitry Andric adjust::ldi::hi8(Size, Fixup, Value, Ctx); 3200b57cec5SDimitry Andric break; 3210b57cec5SDimitry Andric case AVR::fixup_hh8_ldi_neg: 3220b57cec5SDimitry Andric case AVR::fixup_hh8_ldi_pm_neg: 323349cc55cSDimitry Andric if (Kind == AVR::fixup_hh8_ldi_pm_neg) 324349cc55cSDimitry Andric adjust::pm(Value); 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric adjust::ldi::neg(Value); 3270b57cec5SDimitry Andric adjust::ldi::hh8(Size, Fixup, Value, Ctx); 3280b57cec5SDimitry Andric break; 3290b57cec5SDimitry Andric case AVR::fixup_ms8_ldi_neg: 3300b57cec5SDimitry Andric adjust::ldi::neg(Value); 3310b57cec5SDimitry Andric adjust::ldi::ms8(Size, Fixup, Value, Ctx); 3320b57cec5SDimitry Andric break; 3330b57cec5SDimitry Andric case AVR::fixup_16: 3340b57cec5SDimitry Andric adjust::unsigned_width(16, Value, std::string("port number"), Fixup, Ctx); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric Value &= 0xffff; 3370b57cec5SDimitry Andric break; 3380b57cec5SDimitry Andric case AVR::fixup_16_pm: 3390b57cec5SDimitry Andric Value >>= 1; // Flash addresses are always shifted. 3400b57cec5SDimitry Andric adjust::unsigned_width(16, Value, std::string("port number"), Fixup, Ctx); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric Value &= 0xffff; 3430b57cec5SDimitry Andric break; 3440b57cec5SDimitry Andric 3455ffd83dbSDimitry Andric case AVR::fixup_6: 3465ffd83dbSDimitry Andric adjust::fixup_6(Fixup, Value, Ctx); 3475ffd83dbSDimitry Andric break; 3480b57cec5SDimitry Andric case AVR::fixup_6_adiw: 3490b57cec5SDimitry Andric adjust::fixup_6_adiw(Fixup, Value, Ctx); 3500b57cec5SDimitry Andric break; 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric case AVR::fixup_port5: 3530b57cec5SDimitry Andric adjust::fixup_port5(Fixup, Value, Ctx); 3540b57cec5SDimitry Andric break; 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric case AVR::fixup_port6: 3570b57cec5SDimitry Andric adjust::fixup_port6(Fixup, Value, Ctx); 3580b57cec5SDimitry Andric break; 3590b57cec5SDimitry Andric 360bdd1243dSDimitry Andric case AVR::fixup_lds_sts_16: 361bdd1243dSDimitry Andric adjust::fixup_lds_sts_16(Fixup, Value, Ctx); 362bdd1243dSDimitry Andric break; 363bdd1243dSDimitry Andric 3640b57cec5SDimitry Andric // Fixups which do not require adjustments. 3650b57cec5SDimitry Andric case FK_Data_1: 3660b57cec5SDimitry Andric case FK_Data_2: 3670b57cec5SDimitry Andric case FK_Data_4: 3680b57cec5SDimitry Andric case FK_Data_8: 3690b57cec5SDimitry Andric break; 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric case FK_GPRel_4: 3720b57cec5SDimitry Andric llvm_unreachable("don't know how to adjust this fixup"); 3730b57cec5SDimitry Andric break; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter> 3780b57cec5SDimitry Andric AVRAsmBackend::createObjectTargetWriter() const { 3790b57cec5SDimitry Andric return createAVRELFObjectWriter(MCELFObjectTargetWriter::getOSABI(OSType)); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric void AVRAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 3830b57cec5SDimitry Andric const MCValue &Target, 3840b57cec5SDimitry Andric MutableArrayRef<char> Data, uint64_t Value, 3850b57cec5SDimitry Andric bool IsResolved, 3860b57cec5SDimitry Andric const MCSubtargetInfo *STI) const { 387bdd1243dSDimitry Andric if (Fixup.getKind() >= FirstLiteralRelocationKind) 388bdd1243dSDimitry Andric return; 3890b57cec5SDimitry Andric adjustFixupValue(Fixup, Target, Value, &Asm.getContext()); 3900b57cec5SDimitry Andric if (Value == 0) 3910b57cec5SDimitry Andric return; // Doesn't change encoding. 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric // The number of bits in the fixup mask 3960b57cec5SDimitry Andric auto NumBits = Info.TargetSize + Info.TargetOffset; 3970b57cec5SDimitry Andric auto NumBytes = (NumBits / 8) + ((NumBits % 8) == 0 ? 0 : 1); 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric // Shift the value into position. 4000b57cec5SDimitry Andric Value <<= Info.TargetOffset; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric unsigned Offset = Fixup.getOffset(); 4030b57cec5SDimitry Andric assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric // For each byte of the fragment that the fixup touches, mask in the 4060b57cec5SDimitry Andric // bits from the fixup value. 4070b57cec5SDimitry Andric for (unsigned i = 0; i < NumBytes; ++i) { 4080b57cec5SDimitry Andric uint8_t mask = (((Value >> (i * 8)) & 0xff)); 4090b57cec5SDimitry Andric Data[Offset + i] |= mask; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric 413bdd1243dSDimitry Andric std::optional<MCFixupKind> AVRAsmBackend::getFixupKind(StringRef Name) const { 414bdd1243dSDimitry Andric unsigned Type; 415bdd1243dSDimitry Andric Type = llvm::StringSwitch<unsigned>(Name) 416bdd1243dSDimitry Andric #define ELF_RELOC(X, Y) .Case(#X, Y) 417bdd1243dSDimitry Andric #include "llvm/BinaryFormat/ELFRelocs/AVR.def" 418bdd1243dSDimitry Andric #undef ELF_RELOC 419bdd1243dSDimitry Andric .Case("BFD_RELOC_NONE", ELF::R_AVR_NONE) 420bdd1243dSDimitry Andric .Case("BFD_RELOC_16", ELF::R_AVR_16) 421bdd1243dSDimitry Andric .Case("BFD_RELOC_32", ELF::R_AVR_32) 422bdd1243dSDimitry Andric .Default(-1u); 423bdd1243dSDimitry Andric if (Type != -1u) 424bdd1243dSDimitry Andric return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type); 425bdd1243dSDimitry Andric return std::nullopt; 426bdd1243dSDimitry Andric } 427bdd1243dSDimitry Andric 4280b57cec5SDimitry Andric MCFixupKindInfo const &AVRAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { 4290b57cec5SDimitry Andric // NOTE: Many AVR fixups work on sets of non-contignous bits. We work around 4300b57cec5SDimitry Andric // this by saying that the fixup is the size of the entire instruction. 4310b57cec5SDimitry Andric const static MCFixupKindInfo Infos[AVR::NumTargetFixupKinds] = { 4320b57cec5SDimitry Andric // This table *must* be in same the order of fixup_* kinds in 4330b57cec5SDimitry Andric // AVRFixupKinds.h. 4340b57cec5SDimitry Andric // 4350b57cec5SDimitry Andric // name offset bits flags 4360b57cec5SDimitry Andric {"fixup_32", 0, 32, 0}, 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric {"fixup_7_pcrel", 3, 7, MCFixupKindInfo::FKF_IsPCRel}, 4390b57cec5SDimitry Andric {"fixup_13_pcrel", 0, 12, MCFixupKindInfo::FKF_IsPCRel}, 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric {"fixup_16", 0, 16, 0}, 4420b57cec5SDimitry Andric {"fixup_16_pm", 0, 16, 0}, 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric {"fixup_ldi", 0, 8, 0}, 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric {"fixup_lo8_ldi", 0, 8, 0}, 4470b57cec5SDimitry Andric {"fixup_hi8_ldi", 0, 8, 0}, 4480b57cec5SDimitry Andric {"fixup_hh8_ldi", 0, 8, 0}, 4490b57cec5SDimitry Andric {"fixup_ms8_ldi", 0, 8, 0}, 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric {"fixup_lo8_ldi_neg", 0, 8, 0}, 4520b57cec5SDimitry Andric {"fixup_hi8_ldi_neg", 0, 8, 0}, 4530b57cec5SDimitry Andric {"fixup_hh8_ldi_neg", 0, 8, 0}, 4540b57cec5SDimitry Andric {"fixup_ms8_ldi_neg", 0, 8, 0}, 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric {"fixup_lo8_ldi_pm", 0, 8, 0}, 4570b57cec5SDimitry Andric {"fixup_hi8_ldi_pm", 0, 8, 0}, 4580b57cec5SDimitry Andric {"fixup_hh8_ldi_pm", 0, 8, 0}, 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric {"fixup_lo8_ldi_pm_neg", 0, 8, 0}, 4610b57cec5SDimitry Andric {"fixup_hi8_ldi_pm_neg", 0, 8, 0}, 4620b57cec5SDimitry Andric {"fixup_hh8_ldi_pm_neg", 0, 8, 0}, 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric {"fixup_call", 0, 22, 0}, 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric {"fixup_6", 0, 16, 0}, // non-contiguous 4670b57cec5SDimitry Andric {"fixup_6_adiw", 0, 6, 0}, 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric {"fixup_lo8_ldi_gs", 0, 8, 0}, 4700b57cec5SDimitry Andric {"fixup_hi8_ldi_gs", 0, 8, 0}, 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric {"fixup_8", 0, 8, 0}, 4730b57cec5SDimitry Andric {"fixup_8_lo8", 0, 8, 0}, 4740b57cec5SDimitry Andric {"fixup_8_hi8", 0, 8, 0}, 4750b57cec5SDimitry Andric {"fixup_8_hlo8", 0, 8, 0}, 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric {"fixup_diff8", 0, 8, 0}, 4780b57cec5SDimitry Andric {"fixup_diff16", 0, 16, 0}, 4790b57cec5SDimitry Andric {"fixup_diff32", 0, 32, 0}, 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric {"fixup_lds_sts_16", 0, 16, 0}, 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric {"fixup_port6", 0, 16, 0}, // non-contiguous 4840b57cec5SDimitry Andric {"fixup_port5", 3, 5, 0}, 4850b57cec5SDimitry Andric }; 4860b57cec5SDimitry Andric 487bdd1243dSDimitry Andric // Fixup kinds from .reloc directive are like R_AVR_NONE. They do not require 488bdd1243dSDimitry Andric // any extra processing. 489bdd1243dSDimitry Andric if (Kind >= FirstLiteralRelocationKind) 490bdd1243dSDimitry Andric return MCAsmBackend::getFixupKindInfo(FK_NONE); 491bdd1243dSDimitry Andric 4920b57cec5SDimitry Andric if (Kind < FirstTargetFixupKind) 4930b57cec5SDimitry Andric return MCAsmBackend::getFixupKindInfo(Kind); 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 4960b57cec5SDimitry Andric "Invalid kind!"); 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric return Infos[Kind - FirstTargetFixupKind]; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric 501349cc55cSDimitry Andric bool AVRAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, 502349cc55cSDimitry Andric const MCSubtargetInfo *STI) const { 5030b57cec5SDimitry Andric // If the count is not 2-byte aligned, we must be writing data into the text 5040b57cec5SDimitry Andric // section (otherwise we have unaligned instructions, and thus have far 5050b57cec5SDimitry Andric // bigger problems), so just write zeros instead. 5060b57cec5SDimitry Andric assert((Count % 2) == 0 && "NOP instructions must be 2 bytes"); 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric OS.write_zeros(Count); 5090b57cec5SDimitry Andric return true; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric bool AVRAsmBackend::shouldForceRelocation(const MCAssembler &Asm, 5130b57cec5SDimitry Andric const MCFixup &Fixup, 5145f757f3fSDimitry Andric const MCValue &Target, 5155f757f3fSDimitry Andric const MCSubtargetInfo *STI) { 5160b57cec5SDimitry Andric switch ((unsigned)Fixup.getKind()) { 517349cc55cSDimitry Andric default: 518bdd1243dSDimitry Andric return Fixup.getKind() >= FirstLiteralRelocationKind; 5190b57cec5SDimitry Andric case AVR::fixup_7_pcrel: 5200b57cec5SDimitry Andric case AVR::fixup_13_pcrel: 5216c4b055cSDimitry Andric // Always resolve relocations for PC-relative branches 52206c3fb27SDimitry Andric return false; 5230b57cec5SDimitry Andric case AVR::fixup_call: 5240b57cec5SDimitry Andric return true; 5250b57cec5SDimitry Andric } 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric MCAsmBackend *createAVRAsmBackend(const Target &T, const MCSubtargetInfo &STI, 5290b57cec5SDimitry Andric const MCRegisterInfo &MRI, 5300b57cec5SDimitry Andric const llvm::MCTargetOptions &TO) { 5310b57cec5SDimitry Andric return new AVRAsmBackend(STI.getTargetTriple().getOS()); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric } // end of namespace llvm 535