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