1 | //===- MSP430.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 | // The MSP430 is a 16-bit microcontroller RISC architecture. The instruction set |
10 | // has only 27 core instructions orthogonally augmented with a variety |
11 | // of addressing modes for source and destination operands. Entire address space |
12 | // of MSP430 is 64KB (the extended MSP430X architecture is not considered here). |
13 | // A typical MSP430 MCU has several kilobytes of RAM and ROM, plenty |
14 | // of peripherals and is generally optimized for a low power consumption. |
15 | // |
16 | //===----------------------------------------------------------------------===// |
17 | |
18 | #include "Symbols.h" |
19 | #include "Target.h" |
20 | #include "lld/Common/ErrorHandler.h" |
21 | #include "llvm/BinaryFormat/ELF.h" |
22 | #include "llvm/Support/Endian.h" |
23 | |
24 | using namespace llvm; |
25 | using namespace llvm::object; |
26 | using namespace llvm::support::endian; |
27 | using namespace llvm::ELF; |
28 | using namespace lld; |
29 | using namespace lld::elf; |
30 | |
31 | namespace { |
32 | class MSP430 final : public TargetInfo { |
33 | public: |
34 | MSP430(); |
35 | RelExpr getRelExpr(RelType type, const Symbol &s, |
36 | const uint8_t *loc) const override; |
37 | void relocate(uint8_t *loc, const Relocation &rel, |
38 | uint64_t val) const override; |
39 | }; |
40 | } // namespace |
41 | |
42 | MSP430::MSP430() { |
43 | // mov.b #0, r3 |
44 | trapInstr = {0x43, 0x43, 0x43, 0x43}; |
45 | } |
46 | |
47 | RelExpr MSP430::getRelExpr(RelType type, const Symbol &s, |
48 | const uint8_t *loc) const { |
49 | switch (type) { |
50 | case R_MSP430_10_PCREL: |
51 | case R_MSP430_16_PCREL: |
52 | case R_MSP430_16_PCREL_BYTE: |
53 | case R_MSP430_2X_PCREL: |
54 | case R_MSP430_RL_PCREL: |
55 | case R_MSP430_SYM_DIFF: |
56 | return R_PC; |
57 | default: |
58 | return R_ABS; |
59 | } |
60 | } |
61 | |
62 | void MSP430::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { |
63 | switch (rel.type) { |
64 | case R_MSP430_8: |
65 | checkIntUInt(loc, v: val, n: 8, rel); |
66 | *loc = val; |
67 | break; |
68 | case R_MSP430_16: |
69 | case R_MSP430_16_PCREL: |
70 | case R_MSP430_16_BYTE: |
71 | case R_MSP430_16_PCREL_BYTE: |
72 | checkIntUInt(loc, v: val, n: 16, rel); |
73 | write16le(P: loc, V: val); |
74 | break; |
75 | case R_MSP430_32: |
76 | checkIntUInt(loc, v: val, n: 32, rel); |
77 | write32le(P: loc, V: val); |
78 | break; |
79 | case R_MSP430_10_PCREL: { |
80 | int16_t offset = ((int16_t)val >> 1) - 1; |
81 | checkInt(loc, v: offset, n: 10, rel); |
82 | write16le(P: loc, V: (read16le(P: loc) & 0xFC00) | (offset & 0x3FF)); |
83 | break; |
84 | } |
85 | default: |
86 | error(msg: getErrorLocation(loc) + "unrecognized relocation " + |
87 | toString(type: rel.type)); |
88 | } |
89 | } |
90 | |
91 | TargetInfo *elf::getMSP430TargetInfo() { |
92 | static MSP430 target; |
93 | return ⌖ |
94 | } |
95 | |