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 "llvm/BinaryFormat/ELF.h" |
21 | #include "llvm/Support/Endian.h" |
22 | |
23 | using namespace llvm; |
24 | using namespace llvm::object; |
25 | using namespace llvm::support::endian; |
26 | using namespace llvm::ELF; |
27 | using namespace lld; |
28 | using namespace lld::elf; |
29 | |
30 | namespace { |
31 | class MSP430 final : public TargetInfo { |
32 | public: |
33 | MSP430(Ctx &); |
34 | RelExpr getRelExpr(RelType type, const Symbol &s, |
35 | const uint8_t *loc) const override; |
36 | void relocate(uint8_t *loc, const Relocation &rel, |
37 | uint64_t val) const override; |
38 | }; |
39 | } // namespace |
40 | |
41 | MSP430::MSP430(Ctx &ctx) : TargetInfo(ctx) { |
42 | // mov.b #0, r3 |
43 | trapInstr = {0x43, 0x43, 0x43, 0x43}; |
44 | } |
45 | |
46 | RelExpr MSP430::getRelExpr(RelType type, const Symbol &s, |
47 | const uint8_t *loc) const { |
48 | switch (type) { |
49 | case R_MSP430_10_PCREL: |
50 | case R_MSP430_16_PCREL: |
51 | case R_MSP430_16_PCREL_BYTE: |
52 | case R_MSP430_2X_PCREL: |
53 | case R_MSP430_RL_PCREL: |
54 | case R_MSP430_SYM_DIFF: |
55 | return R_PC; |
56 | default: |
57 | return R_ABS; |
58 | } |
59 | } |
60 | |
61 | void MSP430::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { |
62 | switch (rel.type) { |
63 | case R_MSP430_8: |
64 | checkIntUInt(ctx, loc, v: val, n: 8, rel); |
65 | *loc = val; |
66 | break; |
67 | case R_MSP430_16: |
68 | case R_MSP430_16_PCREL: |
69 | case R_MSP430_16_BYTE: |
70 | case R_MSP430_16_PCREL_BYTE: |
71 | checkIntUInt(ctx, loc, v: val, n: 16, rel); |
72 | write16le(P: loc, V: val); |
73 | break; |
74 | case R_MSP430_32: |
75 | checkIntUInt(ctx, loc, v: val, n: 32, rel); |
76 | write32le(P: loc, V: val); |
77 | break; |
78 | case R_MSP430_10_PCREL: { |
79 | int16_t offset = ((int16_t)val >> 1) - 1; |
80 | checkInt(ctx, loc, v: offset, n: 10, rel); |
81 | write16le(P: loc, V: (read16le(P: loc) & 0xFC00) | (offset & 0x3FF)); |
82 | break; |
83 | } |
84 | default: |
85 | Err(ctx) << getErrorLoc(ctx, loc) << "unrecognized relocation " << rel.type; |
86 | } |
87 | } |
88 | |
89 | void elf::setMSP430TargetInfo(Ctx &ctx) { ctx.target.reset(p: new MSP430(ctx)); } |
90 | |