xref: /freebsd/contrib/llvm-project/lld/ELF/Arch/MSP430.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 "Symbols.h"
190b57cec5SDimitry Andric #include "Target.h"
200b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h"
21*81ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
220b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric using namespace llvm::object;
260b57cec5SDimitry Andric using namespace llvm::support::endian;
270b57cec5SDimitry Andric using namespace llvm::ELF;
285ffd83dbSDimitry Andric using namespace lld;
295ffd83dbSDimitry Andric using namespace lld::elf;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric namespace {
320b57cec5SDimitry Andric class MSP430 final : public TargetInfo {
330b57cec5SDimitry Andric public:
340b57cec5SDimitry Andric   MSP430();
350b57cec5SDimitry Andric   RelExpr getRelExpr(RelType type, const Symbol &s,
360b57cec5SDimitry Andric                      const uint8_t *loc) const override;
375ffd83dbSDimitry Andric   void relocate(uint8_t *loc, const Relocation &rel,
385ffd83dbSDimitry Andric                 uint64_t val) const override;
390b57cec5SDimitry Andric };
400b57cec5SDimitry Andric } // namespace
410b57cec5SDimitry Andric 
MSP430()420b57cec5SDimitry Andric MSP430::MSP430() {
430b57cec5SDimitry Andric   // mov.b #0, r3
440b57cec5SDimitry Andric   trapInstr = {0x43, 0x43, 0x43, 0x43};
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
getRelExpr(RelType type,const Symbol & s,const uint8_t * loc) const470b57cec5SDimitry Andric RelExpr MSP430::getRelExpr(RelType type, const Symbol &s,
480b57cec5SDimitry Andric                            const uint8_t *loc) const {
490b57cec5SDimitry Andric   switch (type) {
500b57cec5SDimitry Andric   case R_MSP430_10_PCREL:
510b57cec5SDimitry Andric   case R_MSP430_16_PCREL:
520b57cec5SDimitry Andric   case R_MSP430_16_PCREL_BYTE:
530b57cec5SDimitry Andric   case R_MSP430_2X_PCREL:
540b57cec5SDimitry Andric   case R_MSP430_RL_PCREL:
550b57cec5SDimitry Andric   case R_MSP430_SYM_DIFF:
560b57cec5SDimitry Andric     return R_PC;
570b57cec5SDimitry Andric   default:
580b57cec5SDimitry Andric     return R_ABS;
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
relocate(uint8_t * loc,const Relocation & rel,uint64_t val) const625ffd83dbSDimitry Andric void MSP430::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
635ffd83dbSDimitry Andric   switch (rel.type) {
640b57cec5SDimitry Andric   case R_MSP430_8:
655ffd83dbSDimitry Andric     checkIntUInt(loc, val, 8, rel);
660b57cec5SDimitry Andric     *loc = val;
670b57cec5SDimitry Andric     break;
680b57cec5SDimitry Andric   case R_MSP430_16:
690b57cec5SDimitry Andric   case R_MSP430_16_PCREL:
700b57cec5SDimitry Andric   case R_MSP430_16_BYTE:
710b57cec5SDimitry Andric   case R_MSP430_16_PCREL_BYTE:
725ffd83dbSDimitry Andric     checkIntUInt(loc, val, 16, rel);
730b57cec5SDimitry Andric     write16le(loc, val);
740b57cec5SDimitry Andric     break;
750b57cec5SDimitry Andric   case R_MSP430_32:
765ffd83dbSDimitry Andric     checkIntUInt(loc, val, 32, rel);
770b57cec5SDimitry Andric     write32le(loc, val);
780b57cec5SDimitry Andric     break;
790b57cec5SDimitry Andric   case R_MSP430_10_PCREL: {
800b57cec5SDimitry Andric     int16_t offset = ((int16_t)val >> 1) - 1;
815ffd83dbSDimitry Andric     checkInt(loc, offset, 10, rel);
820b57cec5SDimitry Andric     write16le(loc, (read16le(loc) & 0xFC00) | (offset & 0x3FF));
830b57cec5SDimitry Andric     break;
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric   default:
865ffd83dbSDimitry Andric     error(getErrorLocation(loc) + "unrecognized relocation " +
875ffd83dbSDimitry Andric           toString(rel.type));
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
getMSP430TargetInfo()915ffd83dbSDimitry Andric TargetInfo *elf::getMSP430TargetInfo() {
920b57cec5SDimitry Andric   static MSP430 target;
930b57cec5SDimitry Andric   return ⌖
940b57cec5SDimitry Andric }
95