Coverage Report

Created: 2018-08-19 14:04

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/ELF/Arch/Hexagon.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- Hexagon.cpp -------------------------------------------------------===//
2
//
3
//                             The LLVM Linker
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "InputFiles.h"
11
#include "Symbols.h"
12
#include "Target.h"
13
#include "lld/Common/ErrorHandler.h"
14
#include "llvm/BinaryFormat/ELF.h"
15
#include "llvm/Object/ELF.h"
16
#include "llvm/Support/Endian.h"
17
18
using namespace llvm;
19
using namespace llvm::object;
20
using namespace llvm::support::endian;
21
using namespace llvm::ELF;
22
using namespace lld;
23
using namespace lld::elf;
24
25
namespace {
26
class Hexagon final : public TargetInfo {
27
public:
28
  uint32_t calcEFlags() const override;
29
  RelExpr getRelExpr(RelType Type, const Symbol &S,
30
                     const uint8_t *Loc) const override;
31
  void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
32
};
33
} // namespace
34
35
// Support V60 only at the moment.
36
1
uint32_t Hexagon::calcEFlags() const { return 0x60; }
37
38
71
static uint32_t applyMask(uint32_t Mask, uint32_t Data) {
39
71
  uint32_t Result = 0;
40
71
  size_t Off = 0;
41
71
42
2.34k
  for (size_t Bit = 0; Bit != 32; 
++Bit2.27k
) {
43
2.27k
    uint32_t ValBit = (Data >> Off) & 1;
44
2.27k
    uint32_t MaskBit = (Mask >> Bit) & 1;
45
2.27k
    if (MaskBit) {
46
1.18k
      Result |= (ValBit << Bit);
47
1.18k
      ++Off;
48
1.18k
    }
49
2.27k
  }
50
71
  return Result;
51
71
}
52
53
RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S,
54
71
                            const uint8_t *Loc) const {
55
71
  switch (Type) {
56
71
  case R_HEX_B15_PCREL:
57
8
  case R_HEX_B15_PCREL_X:
58
8
  case R_HEX_B22_PCREL:
59
8
  case R_HEX_B22_PCREL_X:
60
8
  case R_HEX_B32_PCREL_X:
61
8
  case R_HEX_6_PCREL_X:
62
8
    return R_PC;
63
63
  default:
64
63
    return R_ABS;
65
71
  }
66
71
}
67
68
27
static uint32_t findMaskR6(uint32_t Insn) {
69
27
  // There are (arguably too) many relocation masks for the DSP's
70
27
  // R_HEX_6_X type.  The table below is used to select the correct mask
71
27
  // for the given instruction.
72
27
  struct InstructionMask {
73
27
    uint32_t CmpMask;
74
27
    uint32_t RelocMask;
75
27
  };
76
27
77
27
  static const InstructionMask R6[] = {
78
27
      {0x38000000, 0x0000201f}, {0x39000000, 0x0000201f},
79
27
      {0x3e000000, 0x00001f80}, {0x3f000000, 0x00001f80},
80
27
      {0x40000000, 0x000020f8}, {0x41000000, 0x000007e0},
81
27
      {0x42000000, 0x000020f8}, {0x43000000, 0x000007e0},
82
27
      {0x44000000, 0x000020f8}, {0x45000000, 0x000007e0},
83
27
      {0x46000000, 0x000020f8}, {0x47000000, 0x000007e0},
84
27
      {0x6a000000, 0x00001f80}, {0x7c000000, 0x001f2000},
85
27
      {0x9a000000, 0x00000f60}, {0x9b000000, 0x00000f60},
86
27
      {0x9c000000, 0x00000f60}, {0x9d000000, 0x00000f60},
87
27
      {0x9f000000, 0x001f0100}, {0xab000000, 0x0000003f},
88
27
      {0xad000000, 0x0000003f}, {0xaf000000, 0x00030078},
89
27
      {0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0},
90
27
      {0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}};
91
27
92
27
  // Duplex forms have a fixed mask and parse bits 15:14 are always
93
27
  // zero.  Non-duplex insns will always have at least one bit set in the
94
27
  // parse field.
95
27
  if ((0xC000 & Insn) == 0x0)
96
1
    return 0x03f00000;
97
26
98
26
  for (InstructionMask I : R6)
99
351
    if ((0xff000000 & Insn) == I.CmpMask)
100
26
      return I.RelocMask;
101
26
102
26
  error("unrecognized instruction for R_HEX_6 relocation: 0x" +
103
0
        utohexstr(Insn));
104
0
  return 0;
105
26
}
106
107
3
static uint32_t findMaskR8(uint32_t Insn) {
108
3
  if ((0xff000000 & Insn) == 0xde000000)
109
1
    return 0x00e020e8;
110
2
  if ((0xff000000 & Insn) == 0x3c000000)
111
1
    return 0x0000207f;
112
1
  return 0x00001fe0;
113
1
}
114
115
71
static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
116
117
71
void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
118
71
  switch (Type) {
119
71
  case R_HEX_NONE:
120
0
    break;
121
71
  case R_HEX_6_PCREL_X:
122
27
  case R_HEX_6_X:
123
27
    or32le(Loc, applyMask(findMaskR6(read32le(Loc)), Val));
124
27
    break;
125
27
  case R_HEX_8_X:
126
3
    or32le(Loc, applyMask(findMaskR8(read32le(Loc)), Val));
127
3
    break;
128
27
  case R_HEX_12_X:
129
1
    or32le(Loc, applyMask(0x000007e0, Val));
130
1
    break;
131
27
  case R_HEX_32:
132
1
    or32le(Loc, applyMask(0xffffffff, Val));
133
1
    break;
134
30
  case R_HEX_32_6_X:
135
30
    or32le(Loc, applyMask(0x0fff3fff, Val >> 6));
136
30
    break;
137
27
  case R_HEX_B15_PCREL:
138
1
    or32le(Loc, applyMask(0x00df20fe, Val >> 2));
139
1
    break;
140
27
  case R_HEX_B15_PCREL_X:
141
1
    or32le(Loc, applyMask(0x00df20fe, Val & 0x3f));
142
1
    break;
143
27
  case R_HEX_B22_PCREL:
144
1
    or32le(Loc, applyMask(0x1ff3ffe, Val >> 2));
145
1
    break;
146
27
  case R_HEX_B22_PCREL_X:
147
1
    or32le(Loc, applyMask(0x1ff3ffe, Val & 0x3f));
148
1
    break;
149
27
  case R_HEX_B32_PCREL_X:
150
3
    or32le(Loc, applyMask(0x0fff3fff, Val >> 6));
151
3
    break;
152
27
  case R_HEX_HI16:
153
1
    or32le(Loc, applyMask(0x00c03fff, Val >> 16));
154
1
    break;
155
27
  case R_HEX_LO16:
156
1
    or32le(Loc, applyMask(0x00c03fff, Val));
157
1
    break;
158
27
  default:
159
0
    error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type));
160
0
    break;
161
71
  }
162
71
}
163
164
1
TargetInfo *elf::getHexagonTargetInfo() {
165
1
  static Hexagon Target;
166
1
  return &Target;
167
1
}