1 //===- AVR.cpp ------------------------------------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // AVR is a Harvard-architecture 8-bit micrcontroller designed for small 11 // baremetal programs. All AVR-family processors have 32 8-bit registers. 12 // The tiniest AVR has 32 byte RAM and 1 KiB program memory, and the largest 13 // one supports up to 2^24 data address space and 2^22 code address space. 14 // 15 // Since it is a baremetal programming, there's usually no loader to load 16 // ELF files on AVRs. You are expected to link your program against address 17 // 0 and pull out a .text section from the result using objcopy, so that you 18 // can write the linked code to on-chip flush memory. You can do that with 19 // the following commands: 20 // 21 // ld.lld -Ttext=0 -o foo foo.o 22 // objcopy -O binary --only-section=.text foo output.bin 23 // 24 // Note that the current AVR support is very preliminary so you can't 25 // link any useful program yet, though. 26 // 27 //===----------------------------------------------------------------------===// 28 29 #include "Error.h" 30 #include "InputFiles.h" 31 #include "Symbols.h" 32 #include "Target.h" 33 #include "llvm/Object/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 RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, 47 const uint8_t *Loc) const override; 48 void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; 49 }; 50 } // namespace 51 52 RelExpr AVR::getRelExpr(uint32_t Type, const SymbolBody &S, 53 const uint8_t *Loc) const { 54 switch (Type) { 55 case R_AVR_CALL: 56 return R_ABS; 57 default: 58 error(toString(S.File) + ": unknown relocation type: " + toString(Type)); 59 return R_HINT; 60 } 61 } 62 63 void AVR::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { 64 switch (Type) { 65 case R_AVR_CALL: { 66 uint16_t Hi = Val >> 17; 67 uint16_t Lo = Val >> 1; 68 write16le(Loc, read16le(Loc) | ((Hi >> 1) << 4) | (Hi & 1)); 69 write16le(Loc + 2, Lo); 70 break; 71 } 72 default: 73 error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); 74 } 75 } 76 77 TargetInfo *elf::getAVRTargetInfo() { 78 static AVR Target; 79 return &Target; 80 } 81