xref: /freebsd/contrib/llvm-project/lld/ELF/Arch/MSP430.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===- MSP430.cpp ---------------------------------------------------------===//
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 // The MSP430 is a 16-bit microcontroller RISC architecture. The instruction set
100b57cec5SDimitry Andric // has only 27 core instructions orthogonally augmented with a variety
110b57cec5SDimitry Andric // of addressing modes for source and destination operands. Entire address space
120b57cec5SDimitry Andric // of MSP430 is 64KB (the extended MSP430X architecture is not considered here).
130b57cec5SDimitry Andric // A typical MSP430 MCU has several kilobytes of RAM and ROM, plenty
140b57cec5SDimitry Andric // of peripherals and is generally optimized for a low power consumption.
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "InputFiles.h"
190b57cec5SDimitry Andric #include "Symbols.h"
200b57cec5SDimitry Andric #include "Target.h"
210b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h"
220b57cec5SDimitry Andric #include "llvm/Object/ELF.h"
230b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric using namespace llvm::object;
270b57cec5SDimitry Andric using namespace llvm::support::endian;
280b57cec5SDimitry Andric using namespace llvm::ELF;
29*5ffd83dbSDimitry Andric using namespace lld;
30*5ffd83dbSDimitry Andric using namespace lld::elf;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace {
330b57cec5SDimitry Andric class MSP430 final : public TargetInfo {
340b57cec5SDimitry Andric public:
350b57cec5SDimitry Andric   MSP430();
360b57cec5SDimitry Andric   RelExpr getRelExpr(RelType type, const Symbol &s,
370b57cec5SDimitry Andric                      const uint8_t *loc) const override;
38*5ffd83dbSDimitry Andric   void relocate(uint8_t *loc, const Relocation &rel,
39*5ffd83dbSDimitry Andric                 uint64_t val) const override;
400b57cec5SDimitry Andric };
410b57cec5SDimitry Andric } // namespace
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric MSP430::MSP430() {
440b57cec5SDimitry Andric   // mov.b #0, r3
450b57cec5SDimitry Andric   trapInstr = {0x43, 0x43, 0x43, 0x43};
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric RelExpr MSP430::getRelExpr(RelType type, const Symbol &s,
490b57cec5SDimitry Andric                            const uint8_t *loc) const {
500b57cec5SDimitry Andric   switch (type) {
510b57cec5SDimitry Andric   case R_MSP430_10_PCREL:
520b57cec5SDimitry Andric   case R_MSP430_16_PCREL:
530b57cec5SDimitry Andric   case R_MSP430_16_PCREL_BYTE:
540b57cec5SDimitry Andric   case R_MSP430_2X_PCREL:
550b57cec5SDimitry Andric   case R_MSP430_RL_PCREL:
560b57cec5SDimitry Andric   case R_MSP430_SYM_DIFF:
570b57cec5SDimitry Andric     return R_PC;
580b57cec5SDimitry Andric   default:
590b57cec5SDimitry Andric     return R_ABS;
600b57cec5SDimitry Andric   }
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
63*5ffd83dbSDimitry Andric void MSP430::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
64*5ffd83dbSDimitry Andric   switch (rel.type) {
650b57cec5SDimitry Andric   case R_MSP430_8:
66*5ffd83dbSDimitry Andric     checkIntUInt(loc, val, 8, rel);
670b57cec5SDimitry Andric     *loc = val;
680b57cec5SDimitry Andric     break;
690b57cec5SDimitry Andric   case R_MSP430_16:
700b57cec5SDimitry Andric   case R_MSP430_16_PCREL:
710b57cec5SDimitry Andric   case R_MSP430_16_BYTE:
720b57cec5SDimitry Andric   case R_MSP430_16_PCREL_BYTE:
73*5ffd83dbSDimitry Andric     checkIntUInt(loc, val, 16, rel);
740b57cec5SDimitry Andric     write16le(loc, val);
750b57cec5SDimitry Andric     break;
760b57cec5SDimitry Andric   case R_MSP430_32:
77*5ffd83dbSDimitry Andric     checkIntUInt(loc, val, 32, rel);
780b57cec5SDimitry Andric     write32le(loc, val);
790b57cec5SDimitry Andric     break;
800b57cec5SDimitry Andric   case R_MSP430_10_PCREL: {
810b57cec5SDimitry Andric     int16_t offset = ((int16_t)val >> 1) - 1;
82*5ffd83dbSDimitry Andric     checkInt(loc, offset, 10, rel);
830b57cec5SDimitry Andric     write16le(loc, (read16le(loc) & 0xFC00) | (offset & 0x3FF));
840b57cec5SDimitry Andric     break;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric   default:
87*5ffd83dbSDimitry Andric     error(getErrorLocation(loc) + "unrecognized relocation " +
88*5ffd83dbSDimitry Andric           toString(rel.type));
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
92*5ffd83dbSDimitry Andric TargetInfo *elf::getMSP430TargetInfo() {
930b57cec5SDimitry Andric   static MSP430 target;
940b57cec5SDimitry Andric   return ⌖
950b57cec5SDimitry Andric }
96