1 //===- AVR.cpp ------------------------------------------------------------===// 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 // AVR is a Harvard-architecture 8-bit microcontroller designed for small 10 // baremetal programs. All AVR-family processors have 32 8-bit registers. 11 // The tiniest AVR has 32 byte RAM and 1 KiB program memory, and the largest 12 // one supports up to 2^24 data address space and 2^22 code address space. 13 // 14 // Since it is a baremetal programming, there's usually no loader to load 15 // ELF files on AVRs. You are expected to link your program against address 16 // 0 and pull out a .text section from the result using objcopy, so that you 17 // can write the linked code to on-chip flush memory. You can do that with 18 // the following commands: 19 // 20 // ld.lld -Ttext=0 -o foo foo.o 21 // objcopy -O binary --only-section=.text foo output.bin 22 // 23 // Note that the current AVR support is very preliminary so you can't 24 // link any useful program yet, though. 25 // 26 //===----------------------------------------------------------------------===// 27 28 #include "InputFiles.h" 29 #include "Symbols.h" 30 #include "Target.h" 31 #include "Thunks.h" 32 #include "lld/Common/ErrorHandler.h" 33 #include "llvm/BinaryFormat/ELF.h" 34 #include "llvm/Support/Endian.h" 35 36 using namespace llvm; 37 using namespace llvm::object; 38 using namespace llvm::support::endian; 39 using namespace llvm::ELF; 40 using namespace lld; 41 using namespace lld::elf; 42 43 namespace { 44 class AVR final : public TargetInfo { 45 public: 46 AVR() { needsThunks = true; } 47 uint32_t calcEFlags() const override; 48 RelExpr getRelExpr(RelType type, const Symbol &s, 49 const uint8_t *loc) const override; 50 bool needsThunk(RelExpr expr, RelType type, const InputFile *file, 51 uint64_t branchAddr, const Symbol &s, 52 int64_t a) const override; 53 void relocate(uint8_t *loc, const Relocation &rel, 54 uint64_t val) const override; 55 }; 56 } // namespace 57 58 RelExpr AVR::getRelExpr(RelType type, const Symbol &s, 59 const uint8_t *loc) const { 60 switch (type) { 61 case R_AVR_6: 62 case R_AVR_6_ADIW: 63 case R_AVR_8: 64 case R_AVR_8_LO8: 65 case R_AVR_8_HI8: 66 case R_AVR_8_HLO8: 67 case R_AVR_16: 68 case R_AVR_16_PM: 69 case R_AVR_32: 70 case R_AVR_LDI: 71 case R_AVR_LO8_LDI: 72 case R_AVR_LO8_LDI_NEG: 73 case R_AVR_HI8_LDI: 74 case R_AVR_HI8_LDI_NEG: 75 case R_AVR_HH8_LDI_NEG: 76 case R_AVR_HH8_LDI: 77 case R_AVR_MS8_LDI_NEG: 78 case R_AVR_MS8_LDI: 79 case R_AVR_LO8_LDI_GS: 80 case R_AVR_LO8_LDI_PM: 81 case R_AVR_LO8_LDI_PM_NEG: 82 case R_AVR_HI8_LDI_GS: 83 case R_AVR_HI8_LDI_PM: 84 case R_AVR_HI8_LDI_PM_NEG: 85 case R_AVR_HH8_LDI_PM: 86 case R_AVR_HH8_LDI_PM_NEG: 87 case R_AVR_LDS_STS_16: 88 case R_AVR_PORT5: 89 case R_AVR_PORT6: 90 case R_AVR_CALL: 91 return R_ABS; 92 case R_AVR_7_PCREL: 93 case R_AVR_13_PCREL: 94 return R_PC; 95 default: 96 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + 97 ") against symbol " + toString(s)); 98 return R_NONE; 99 } 100 } 101 102 static void writeLDI(uint8_t *loc, uint64_t val) { 103 write16le(loc, (read16le(loc) & 0xf0f0) | (val & 0xf0) << 4 | (val & 0x0f)); 104 } 105 106 bool AVR::needsThunk(RelExpr expr, RelType type, const InputFile *file, 107 uint64_t branchAddr, const Symbol &s, int64_t a) const { 108 switch (type) { 109 case R_AVR_LO8_LDI_GS: 110 case R_AVR_HI8_LDI_GS: 111 // A thunk is needed if the symbol's virtual address is out of range 112 // [0, 0x1ffff]. 113 return s.getVA() >= 0x20000; 114 default: 115 return false; 116 } 117 } 118 119 void AVR::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { 120 switch (rel.type) { 121 case R_AVR_8: 122 checkUInt(loc, val, 8, rel); 123 *loc = val; 124 break; 125 case R_AVR_8_LO8: 126 checkUInt(loc, val, 32, rel); 127 *loc = val & 0xff; 128 break; 129 case R_AVR_8_HI8: 130 checkUInt(loc, val, 32, rel); 131 *loc = (val >> 8) & 0xff; 132 break; 133 case R_AVR_8_HLO8: 134 checkUInt(loc, val, 32, rel); 135 *loc = (val >> 16) & 0xff; 136 break; 137 case R_AVR_16: 138 // Note: this relocation is often used between code and data space, which 139 // are 0x800000 apart in the output ELF file. The bitmask cuts off the high 140 // bit. 141 write16le(loc, val & 0xffff); 142 break; 143 case R_AVR_16_PM: 144 checkAlignment(loc, val, 2, rel); 145 checkUInt(loc, val >> 1, 16, rel); 146 write16le(loc, val >> 1); 147 break; 148 case R_AVR_32: 149 checkUInt(loc, val, 32, rel); 150 write32le(loc, val); 151 break; 152 153 case R_AVR_LDI: 154 checkUInt(loc, val, 8, rel); 155 writeLDI(loc, val & 0xff); 156 break; 157 158 case R_AVR_LO8_LDI_NEG: 159 writeLDI(loc, -val & 0xff); 160 break; 161 case R_AVR_LO8_LDI: 162 writeLDI(loc, val & 0xff); 163 break; 164 case R_AVR_HI8_LDI_NEG: 165 writeLDI(loc, (-val >> 8) & 0xff); 166 break; 167 case R_AVR_HI8_LDI: 168 writeLDI(loc, (val >> 8) & 0xff); 169 break; 170 case R_AVR_HH8_LDI_NEG: 171 writeLDI(loc, (-val >> 16) & 0xff); 172 break; 173 case R_AVR_HH8_LDI: 174 writeLDI(loc, (val >> 16) & 0xff); 175 break; 176 case R_AVR_MS8_LDI_NEG: 177 writeLDI(loc, (-val >> 24) & 0xff); 178 break; 179 case R_AVR_MS8_LDI: 180 writeLDI(loc, (val >> 24) & 0xff); 181 break; 182 183 case R_AVR_LO8_LDI_GS: 184 checkUInt(loc, val, 17, rel); 185 [[fallthrough]]; 186 case R_AVR_LO8_LDI_PM: 187 checkAlignment(loc, val, 2, rel); 188 writeLDI(loc, (val >> 1) & 0xff); 189 break; 190 case R_AVR_HI8_LDI_GS: 191 checkUInt(loc, val, 17, rel); 192 [[fallthrough]]; 193 case R_AVR_HI8_LDI_PM: 194 checkAlignment(loc, val, 2, rel); 195 writeLDI(loc, (val >> 9) & 0xff); 196 break; 197 case R_AVR_HH8_LDI_PM: 198 checkAlignment(loc, val, 2, rel); 199 writeLDI(loc, (val >> 17) & 0xff); 200 break; 201 202 case R_AVR_LO8_LDI_PM_NEG: 203 checkAlignment(loc, val, 2, rel); 204 writeLDI(loc, (-val >> 1) & 0xff); 205 break; 206 case R_AVR_HI8_LDI_PM_NEG: 207 checkAlignment(loc, val, 2, rel); 208 writeLDI(loc, (-val >> 9) & 0xff); 209 break; 210 case R_AVR_HH8_LDI_PM_NEG: 211 checkAlignment(loc, val, 2, rel); 212 writeLDI(loc, (-val >> 17) & 0xff); 213 break; 214 215 case R_AVR_LDS_STS_16: { 216 checkUInt(loc, val, 7, rel); 217 const uint16_t hi = val >> 4; 218 const uint16_t lo = val & 0xf; 219 write16le(loc, (read16le(loc) & 0xf8f0) | ((hi << 8) | lo)); 220 break; 221 } 222 223 case R_AVR_PORT5: 224 checkUInt(loc, val, 5, rel); 225 write16le(loc, (read16le(loc) & 0xff07) | (val << 3)); 226 break; 227 case R_AVR_PORT6: 228 checkUInt(loc, val, 6, rel); 229 write16le(loc, (read16le(loc) & 0xf9f0) | (val & 0x30) << 5 | (val & 0x0f)); 230 break; 231 232 // Since every jump destination is word aligned we gain an extra bit 233 case R_AVR_7_PCREL: { 234 checkInt(loc, val, 7, rel); 235 checkAlignment(loc, val, 2, rel); 236 const uint16_t target = (val - 2) >> 1; 237 write16le(loc, (read16le(loc) & 0xfc07) | ((target & 0x7f) << 3)); 238 break; 239 } 240 case R_AVR_13_PCREL: { 241 checkAlignment(loc, val, 2, rel); 242 const uint16_t target = (val - 2) >> 1; 243 write16le(loc, (read16le(loc) & 0xf000) | (target & 0xfff)); 244 break; 245 } 246 247 case R_AVR_6: 248 checkInt(loc, val, 6, rel); 249 write16le(loc, (read16le(loc) & 0xd3f8) | (val & 0x20) << 8 | 250 (val & 0x18) << 7 | (val & 0x07)); 251 break; 252 case R_AVR_6_ADIW: 253 checkInt(loc, val, 6, rel); 254 write16le(loc, (read16le(loc) & 0xff30) | (val & 0x30) << 2 | (val & 0x0F)); 255 break; 256 257 case R_AVR_CALL: { 258 uint16_t hi = val >> 17; 259 uint16_t lo = val >> 1; 260 write16le(loc, read16le(loc) | ((hi >> 1) << 4) | (hi & 1)); 261 write16le(loc + 2, lo); 262 break; 263 } 264 default: 265 llvm_unreachable("unknown relocation"); 266 } 267 } 268 269 TargetInfo *elf::getAVRTargetInfo() { 270 static AVR target; 271 return ⌖ 272 } 273 274 static uint32_t getEFlags(InputFile *file) { 275 return cast<ObjFile<ELF32LE>>(file)->getObj().getHeader().e_flags; 276 } 277 278 uint32_t AVR::calcEFlags() const { 279 assert(!ctx.objectFiles.empty()); 280 281 uint32_t flags = getEFlags(ctx.objectFiles[0]); 282 bool hasLinkRelaxFlag = flags & EF_AVR_LINKRELAX_PREPARED; 283 284 for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) { 285 uint32_t objFlags = getEFlags(f); 286 if ((objFlags & EF_AVR_ARCH_MASK) != (flags & EF_AVR_ARCH_MASK)) 287 error(toString(f) + 288 ": cannot link object files with incompatible target ISA"); 289 if (!(objFlags & EF_AVR_LINKRELAX_PREPARED)) 290 hasLinkRelaxFlag = false; 291 } 292 293 if (!hasLinkRelaxFlag) 294 flags &= ~EF_AVR_LINKRELAX_PREPARED; 295 296 return flags; 297 } 298