LLVM 23.0.0git
hexagon.h
Go to the documentation of this file.
1//===---- hexagon.h - JITLink hexagon edge kinds, utilities -----*- C++ -*-===//
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// Generic utilities for graphs representing Hexagon objects.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_JITLINK_HEXAGON_H
14#define LLVM_EXECUTIONENGINE_JITLINK_HEXAGON_H
15
19
21
22/// Represents Hexagon fixup kinds.
23enum EdgeKind_hexagon : Edge::Kind {
24 /// Full 32-bit absolute pointer.
25 /// Fixup <- Target + Addend : uint32
26 Pointer32 = Edge::FirstRelocation,
27
28 /// 32-bit PC-relative.
29 /// Fixup <- Target - Fixup + Addend : int32
31
32 /// 22-bit PC-relative branch (shifted right by 2).
33 /// Fixup <- (Target - Fixup + Addend) >> 2 : int22
34 /// Mask: 0x01ff3ffe
36
37 /// 15-bit PC-relative branch (shifted right by 2).
38 /// Fixup <- (Target - Fixup + Addend) >> 2 : int15
39 /// Mask: 0x00df20fe
41
42 /// 13-bit PC-relative branch (shifted right by 2).
43 /// Fixup <- (Target - Fixup + Addend) >> 2 : int13
44 /// Mask: 0x00202ffe
46
47 /// 9-bit PC-relative branch (shifted right by 2).
48 /// Fixup <- (Target - Fixup + Addend) >> 2 : int9
49 /// Mask: 0x003000fe
51
52 /// 7-bit PC-relative branch (shifted right by 2).
53 /// Fixup <- (Target - Fixup + Addend) >> 2 : int7
54 /// Mask: 0x00001f18
56
57 /// High 16 bits of absolute address.
58 /// Fixup <- (Target + Addend) >> 16
59 /// Mask: 0x00c03fff
61
62 /// Low 16 bits of absolute address.
63 /// Fixup <- (Target + Addend) & 0xffff
64 /// Mask: 0x00c03fff
66
67 /// 32-bit absolute, upper 26 bits via constant extender (shifted right by 6).
68 /// Fixup <- (Target + Addend) >> 6
69 /// Mask: 0x0fff3fff
71
72 /// 32-bit PC-relative, upper 26 bits via constant extender (shifted by 6).
73 /// Fixup <- (Target - Fixup + Addend) >> 6
74 /// Mask: 0x0fff3fff
76
77 /// 22-bit PC-relative branch, lower 6 bits via extender.
78 /// Fixup <- (Target - Fixup + Addend) & 0x3f
79 /// Mask: 0x01ff3ffe
81
82 /// 15-bit PC-relative branch, lower 6 bits via extender.
83 /// Fixup <- (Target - Fixup + Addend) & 0x3f
84 /// Mask: 0x00df20fe
86
87 /// 13-bit PC-relative branch, lower 6 bits via extender.
88 /// Fixup <- (Target - Fixup + Addend) & 0x3f
89 /// Mask: 0x00202ffe
91
92 /// 9-bit PC-relative branch, lower 6 bits via extender.
93 /// Fixup <- (Target - Fixup + Addend) & 0x3f
94 /// Mask: 0x003000fe
96
97 /// 7-bit PC-relative branch, lower 6 bits via extender.
98 /// Fixup <- (Target - Fixup + Addend) & 0x3f
99 /// Mask: 0x00001f18
101
102 /// 6-bit absolute extended.
103 /// Fixup <- (Target + Addend) & mask (instruction-dependent)
105
106 /// 6-bit PC-relative extended.
107 /// Fixup <- (Target - Fixup + Addend) & mask (instruction-dependent)
109
110 /// 8-bit absolute extended.
112
113 /// 9-bit absolute extended (6 effective bits).
115
116 /// 10-bit absolute extended (6 effective bits).
118
119 /// 11-bit absolute extended (6 effective bits).
121
122 /// 12-bit absolute extended.
124
125 /// 16-bit absolute extended (6 effective bits).
127};
128
129/// Returns a string name for the given Hexagon edge kind.
130LLVM_ABI const char *getEdgeKindName(Edge::Kind K);
131
132/// Hexagon pointer size.
133constexpr uint32_t PointerSize = 4;
134
135/// Spread data bits into instruction word according to mask.
136/// For each set bit in mask (scanning low to high), the corresponding
137/// bit position in the result gets the next data bit.
139 uint32_t Result = 0;
140 size_t Off = 0;
141 for (size_t Bit = 0; Bit != 32; ++Bit) {
142 uint32_t ValBit = (Data >> Off) & 1;
143 uint32_t MaskBit = (Mask >> Bit) & 1;
144 if (MaskBit) {
145 Result |= (ValBit << Bit);
146 ++Off;
147 }
148 }
149 return Result;
150}
151
152/// Instruction mask entry for R_HEX_6_X / R_HEX_16_X lookup.
157
158/// Mask table for R_HEX_6_X relocations, indexed by instruction class.
159inline constexpr InstructionMask R6Masks[] = {
160 {0x38000000, 0x0000201f}, {0x39000000, 0x0000201f},
161 {0x3e000000, 0x00001f80}, {0x3f000000, 0x00001f80},
162 {0x40000000, 0x000020f8}, {0x41000000, 0x000007e0},
163 {0x42000000, 0x000020f8}, {0x43000000, 0x000007e0},
164 {0x44000000, 0x000020f8}, {0x45000000, 0x000007e0},
165 {0x46000000, 0x000020f8}, {0x47000000, 0x000007e0},
166 {0x6a000000, 0x00001f80}, {0x7c000000, 0x001f2000},
167 {0x9a000000, 0x00000f60}, {0x9b000000, 0x00000f60},
168 {0x9c000000, 0x00000f60}, {0x9d000000, 0x00000f60},
169 {0x9f000000, 0x001f0100}, {0xab000000, 0x0000003f},
170 {0xad000000, 0x0000003f}, {0xaf000000, 0x00030078},
171 {0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0},
172 {0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}};
173
174inline constexpr uint32_t InstParsePacketEnd = 0x0000c000;
175
176inline bool isDuplex(uint32_t Insn) { return (InstParsePacketEnd & Insn) == 0; }
177
179 if (isDuplex(Insn))
180 return 0x03f00000;
181 for (auto &I : R6Masks)
182 if ((0xff000000 & Insn) == I.CmpMask)
183 return I.RelocMask;
184 return make_error<JITLinkError>("unrecognized instruction for R_HEX_6_X "
185 "relocation: 0x" +
186 utohexstr(Insn));
187}
188
190 if (isDuplex(Insn))
191 return 0x03f00000;
192 if ((0xff000000 & Insn) == 0xde000000)
193 return 0x00e020e8;
194 if ((0xff000000 & Insn) == 0x3c000000)
195 return 0x0000207f;
196 return 0x00001fe0;
197}
198
200 if (isDuplex(Insn))
201 return 0x03f00000;
202 if ((0xff000000 & Insn) == 0xa1000000)
203 return 0x060020ff;
204 return 0x06003fe0;
205}
206
208 if (isDuplex(Insn))
209 return 0x03f00000;
210 Insn = Insn & ~InstParsePacketEnd;
211 if ((0xff000000 & Insn) == 0x48000000)
212 return 0x061f20ff;
213 if ((0xff000000 & Insn) == 0x49000000)
214 return 0x061f3fe0;
215 if ((0xff000000 & Insn) == 0x78000000)
216 return 0x00df3fe0;
217 if ((0xff000000 & Insn) == 0xb0000000)
218 return 0x0fe03fe0;
219 if ((0xff802000 & Insn) == 0x74000000)
220 return 0x00001fe0;
221 if ((0xff802000 & Insn) == 0x74002000)
222 return 0x00001fe0;
223 if ((0xff802000 & Insn) == 0x74800000)
224 return 0x00001fe0;
225 if ((0xff802000 & Insn) == 0x74802000)
226 return 0x00001fe0;
227 for (auto &I : R6Masks)
228 if ((0xff000000 & Insn) == I.CmpMask)
229 return I.RelocMask;
230 return make_error<JITLinkError>("unrecognized instruction for R_HEX_16_X "
231 "relocation: 0x" +
232 utohexstr(Insn));
233}
234
235/// Apply fixup expression for edge to block content.
236inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
237 using namespace llvm::support;
238
239 char *BlockWorkingMem = B.getAlreadyMutableContent().data();
240 char *FixupPtr = BlockWorkingMem + E.getOffset();
241 auto FixupAddress = B.getAddress() + E.getOffset();
242
243 int64_t TargetAddr = E.getTarget().getAddress().getValue() + E.getAddend();
244 int64_t PCRelVal = E.getTarget().getAddress().getValue() -
245 FixupAddress.getValue() + E.getAddend();
246
247 auto or32le = [](char *P, uint32_t V) {
249 };
250
251 uint32_t Insn = endian::read32le(FixupPtr);
252
253 switch (E.getKind()) {
254 case Pointer32:
255 endian::write32le(FixupPtr, static_cast<uint32_t>(TargetAddr));
256 break;
257
258 case PCRel32:
259 endian::write32le(FixupPtr, static_cast<uint32_t>(PCRelVal));
260 break;
261
262 case B22_PCREL:
263 if (!isInt<24>(PCRelVal))
264 return makeTargetOutOfRangeError(G, B, E);
265 or32le(FixupPtr, applyMask(0x01ff3ffe, PCRelVal >> 2));
266 break;
267
268 case B15_PCREL:
269 if (!isInt<17>(PCRelVal))
270 return makeTargetOutOfRangeError(G, B, E);
271 or32le(FixupPtr, applyMask(0x00df20fe, PCRelVal >> 2));
272 break;
273
274 case B13_PCREL:
275 if (!isInt<15>(PCRelVal))
276 return makeTargetOutOfRangeError(G, B, E);
277 or32le(FixupPtr, applyMask(0x00202ffe, PCRelVal >> 2));
278 break;
279
280 case B9_PCREL:
281 if (!isInt<11>(PCRelVal))
282 return makeTargetOutOfRangeError(G, B, E);
283 or32le(FixupPtr, applyMask(0x003000fe, PCRelVal >> 2));
284 break;
285
286 case B7_PCREL:
287 if (!isInt<9>(PCRelVal))
288 return makeTargetOutOfRangeError(G, B, E);
289 or32le(FixupPtr, applyMask(0x00001f18, PCRelVal >> 2));
290 break;
291
292 case HI16:
293 or32le(FixupPtr, applyMask(0x00c03fff, TargetAddr >> 16));
294 break;
295
296 case LO16:
297 or32le(FixupPtr, applyMask(0x00c03fff, TargetAddr));
298 break;
299
300 case Word32_6_X:
301 or32le(FixupPtr, applyMask(0x0fff3fff, TargetAddr >> 6));
302 break;
303
304 case B32_PCREL_X:
305 or32le(FixupPtr, applyMask(0x0fff3fff, PCRelVal >> 6));
306 break;
307
308 case B22_PCREL_X:
309 or32le(FixupPtr, applyMask(0x01ff3ffe, PCRelVal & 0x3f));
310 break;
311
312 case B15_PCREL_X:
313 or32le(FixupPtr, applyMask(0x00df20fe, PCRelVal & 0x3f));
314 break;
315
316 case B13_PCREL_X:
317 or32le(FixupPtr, applyMask(0x00202ffe, PCRelVal & 0x3f));
318 break;
319
320 case B9_PCREL_X:
321 or32le(FixupPtr, applyMask(0x003000fe, PCRelVal & 0x3f));
322 break;
323
324 case B7_PCREL_X:
325 or32le(FixupPtr, applyMask(0x00001f18, PCRelVal & 0x3f));
326 break;
327
328 case Word6_X: {
329 auto Mask = findMaskR6(Insn);
330 if (!Mask)
331 return Mask.takeError();
332 or32le(FixupPtr, applyMask(*Mask, TargetAddr));
333 break;
334 }
335
336 case Word6_PCREL_X: {
337 auto Mask = findMaskR6(Insn);
338 if (!Mask)
339 return Mask.takeError();
340 or32le(FixupPtr, applyMask(*Mask, PCRelVal));
341 break;
342 }
343
344 case Word8_X: {
345 auto Mask = findMaskR8(Insn);
346 if (!Mask)
347 return Mask.takeError();
348 or32le(FixupPtr, applyMask(*Mask, TargetAddr));
349 break;
350 }
351
352 case Word9_X:
353 or32le(FixupPtr, applyMask(0x00003fe0, TargetAddr & 0x3f));
354 break;
355
356 case Word10_X:
357 or32le(FixupPtr, applyMask(0x00203fe0, TargetAddr & 0x3f));
358 break;
359
360 case Word11_X: {
361 auto Mask = findMaskR11(Insn);
362 if (!Mask)
363 return Mask.takeError();
364 or32le(FixupPtr, applyMask(*Mask, TargetAddr & 0x3f));
365 break;
366 }
367
368 case Word12_X:
369 or32le(FixupPtr, applyMask(0x000007e0, TargetAddr));
370 break;
371
372 case Word16_X: {
373 auto Mask = findMaskR16(Insn);
374 if (!Mask)
375 return Mask.takeError();
376 or32le(FixupPtr, applyMask(*Mask, TargetAddr & 0x3f));
377 break;
378 }
379
380 default:
382 "In graph " + G.getName() + ", section " + B.getSection().getName() +
383 " unsupported Hexagon edge kind " + getEdgeKindName(E.getKind()));
384 }
385
386 return Error::success();
387}
388
389} // namespace llvm::jitlink::hexagon
390
391#endif // LLVM_EXECUTIONENGINE_JITLINK_HEXAGON_H
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
#define P(N)
This file contains some functions that are useful when dealing with strings.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
void write32le(void *P, uint32_t V)
Definition Endian.h:475
uint32_t read32le(const void *P)
Definition Endian.h:432
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
static void or32le(void *P, int32_t V)