xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===-- AVRELFObjectWriter.cpp - AVR ELF Writer ---------------------------===//
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 "MCTargetDesc/AVRFixupKinds.h"
10 #include "MCTargetDesc/AVRMCAsmInfo.h"
11 #include "MCTargetDesc/AVRMCTargetDesc.h"
12 
13 #include "llvm/MC/MCAssembler.h"
14 #include "llvm/MC/MCELFObjectWriter.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCObjectWriter.h"
17 #include "llvm/MC/MCValue.h"
18 #include "llvm/Support/ErrorHandling.h"
19 
20 namespace llvm {
21 
22 /// Writes AVR machine code into an ELF32 object file.
23 class AVRELFObjectWriter : public MCELFObjectTargetWriter {
24 public:
25   AVRELFObjectWriter(uint8_t OSABI);
26 
27   virtual ~AVRELFObjectWriter() = default;
28 
29   unsigned getRelocType(const MCFixup &, const MCValue &,
30                         bool IsPCRel) const override;
31 };
32 
33 AVRELFObjectWriter::AVRELFObjectWriter(uint8_t OSABI)
34     : MCELFObjectTargetWriter(false, OSABI, ELF::EM_AVR, true) {}
35 
36 unsigned AVRELFObjectWriter::getRelocType(const MCFixup &Fixup,
37                                           const MCValue &Target,
38                                           bool IsPCRel) const {
39   auto Spec = Target.getSpecifier();
40   switch ((unsigned)Fixup.getKind()) {
41   case FK_Data_1:
42     switch (Spec) {
43     default:
44       llvm_unreachable("Unsupported Modifier");
45     case AVR::S_None:
46       return ELF::R_AVR_8;
47     case AVR::S_DIFF8:
48       return ELF::R_AVR_DIFF8;
49     case AVR::S_LO8:
50       return ELF::R_AVR_8_LO8;
51     case AVR::S_HI8:
52       return ELF::R_AVR_8_HI8;
53     case AVR::S_HH8:
54       return ELF::R_AVR_8_HLO8;
55     }
56   case FK_Data_4:
57     switch (Spec) {
58     default:
59       llvm_unreachable("Unsupported Modifier");
60     case AVR::S_None:
61       return ELF::R_AVR_32;
62     case AVR::S_DIFF32:
63       return ELF::R_AVR_DIFF32;
64     }
65   case FK_Data_2:
66     switch (Spec) {
67     default:
68       llvm_unreachable("Unsupported Modifier");
69     case AVR::S_None:
70       return ELF::R_AVR_16;
71     case AVR::S_AVR_NONE:
72     case AVR::S_PM:
73       return ELF::R_AVR_16_PM;
74     case AVR::S_DIFF16:
75       return ELF::R_AVR_DIFF16;
76     }
77   case AVR::fixup_32:
78     return ELF::R_AVR_32;
79   case AVR::fixup_7_pcrel:
80     return ELF::R_AVR_7_PCREL;
81   case AVR::fixup_13_pcrel:
82     return ELF::R_AVR_13_PCREL;
83   case AVR::fixup_16:
84     return ELF::R_AVR_16;
85   case AVR::fixup_16_pm:
86     return ELF::R_AVR_16_PM;
87   case AVR::fixup_lo8_ldi:
88     return ELF::R_AVR_LO8_LDI;
89   case AVR::fixup_hi8_ldi:
90     return ELF::R_AVR_HI8_LDI;
91   case AVR::fixup_hh8_ldi:
92     return ELF::R_AVR_HH8_LDI;
93   case AVR::fixup_lo8_ldi_neg:
94     return ELF::R_AVR_LO8_LDI_NEG;
95   case AVR::fixup_hi8_ldi_neg:
96     return ELF::R_AVR_HI8_LDI_NEG;
97   case AVR::fixup_hh8_ldi_neg:
98     return ELF::R_AVR_HH8_LDI_NEG;
99   case AVR::fixup_lo8_ldi_pm:
100     return ELF::R_AVR_LO8_LDI_PM;
101   case AVR::fixup_hi8_ldi_pm:
102     return ELF::R_AVR_HI8_LDI_PM;
103   case AVR::fixup_hh8_ldi_pm:
104     return ELF::R_AVR_HH8_LDI_PM;
105   case AVR::fixup_lo8_ldi_pm_neg:
106     return ELF::R_AVR_LO8_LDI_PM_NEG;
107   case AVR::fixup_hi8_ldi_pm_neg:
108     return ELF::R_AVR_HI8_LDI_PM_NEG;
109   case AVR::fixup_hh8_ldi_pm_neg:
110     return ELF::R_AVR_HH8_LDI_PM_NEG;
111   case AVR::fixup_call:
112     return ELF::R_AVR_CALL;
113   case AVR::fixup_ldi:
114     return ELF::R_AVR_LDI;
115   case AVR::fixup_6:
116     return ELF::R_AVR_6;
117   case AVR::fixup_6_adiw:
118     return ELF::R_AVR_6_ADIW;
119   case AVR::fixup_ms8_ldi:
120     return ELF::R_AVR_MS8_LDI;
121   case AVR::fixup_ms8_ldi_neg:
122     return ELF::R_AVR_MS8_LDI_NEG;
123   case AVR::fixup_lo8_ldi_gs:
124     return ELF::R_AVR_LO8_LDI_GS;
125   case AVR::fixup_hi8_ldi_gs:
126     return ELF::R_AVR_HI8_LDI_GS;
127   case AVR::fixup_8:
128     return ELF::R_AVR_8;
129   case AVR::fixup_8_lo8:
130     return ELF::R_AVR_8_LO8;
131   case AVR::fixup_8_hi8:
132     return ELF::R_AVR_8_HI8;
133   case AVR::fixup_8_hlo8:
134     return ELF::R_AVR_8_HLO8;
135   case AVR::fixup_diff8:
136     return ELF::R_AVR_DIFF8;
137   case AVR::fixup_diff16:
138     return ELF::R_AVR_DIFF16;
139   case AVR::fixup_diff32:
140     return ELF::R_AVR_DIFF32;
141   case AVR::fixup_lds_sts_16:
142     return ELF::R_AVR_LDS_STS_16;
143   case AVR::fixup_port6:
144     return ELF::R_AVR_PORT6;
145   case AVR::fixup_port5:
146     return ELF::R_AVR_PORT5;
147   default:
148     llvm_unreachable("invalid fixup kind!");
149   }
150 }
151 
152 std::unique_ptr<MCObjectTargetWriter> createAVRELFObjectWriter(uint8_t OSABI) {
153   return std::make_unique<AVRELFObjectWriter>(OSABI);
154 }
155 
156 } // end of namespace llvm
157