@@ -41,6 +41,50 @@ enum EdgeKind_loongarch : Edge::Kind {
4141 // /
4242 Pointer32,
4343
44+ // / A 16-bit PC-relative branch.
45+ // /
46+ // / Represents a PC-relative branch to a target within +/-128Kb. The target
47+ // / must be 4-byte aligned.
48+ // /
49+ // / Fixup expression:
50+ // / Fixup <- (Target - Fixup + Addend) >> 2 : int16
51+ // /
52+ // / Notes:
53+ // / The '16' in the name refers to the number operand bits and follows the
54+ // / naming convention used by the corresponding ELF relocations. Since the low
55+ // / two bits must be zero (because of the 4-byte alignment of the target) the
56+ // / operand is effectively a signed 18-bit number.
57+ // /
58+ // / Errors:
59+ // / - The result of the unshifted part of the fixup expression must be
60+ // / 4-byte aligned otherwise an alignment error will be returned.
61+ // / - The result of the fixup expression must fit into an int16 otherwise an
62+ // / out-of-range error will be returned.
63+ // /
64+ Branch16PCRel,
65+
66+ // / A 21-bit PC-relative branch.
67+ // /
68+ // / Represents a PC-relative branch to a target within +/-4Mb. The Target must
69+ // / be 4-byte aligned.
70+ // /
71+ // / Fixup expression:
72+ // / Fixup <- (Target - Fixup + Addend) >> 2 : int21
73+ // /
74+ // / Notes:
75+ // / The '21' in the name refers to the number operand bits and follows the
76+ // / naming convention used by the corresponding ELF relocations. Since the low
77+ // / two bits must be zero (because of the 4-byte alignment of the target) the
78+ // / operand is effectively a signed 23-bit number.
79+ // /
80+ // / Errors:
81+ // / - The result of the unshifted part of the fixup expression must be
82+ // / 4-byte aligned otherwise an alignment error will be returned.
83+ // / - The result of the fixup expression must fit into an int21 otherwise an
84+ // / out-of-range error will be returned.
85+ // /
86+ Branch21PCRel,
87+
4488 // / A 26-bit PC-relative branch.
4589 // /
4690 // / Represents a PC-relative call or branch to a target within +/-128Mb. The
@@ -213,6 +257,37 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
213257 *(ulittle32_t *)FixupPtr = Value;
214258 break ;
215259 }
260+ case Branch16PCRel: {
261+ int64_t Value = TargetAddress - FixupAddress + Addend;
262+
263+ if (!isInt<18 >(Value))
264+ return makeTargetOutOfRangeError (G, B, E);
265+
266+ if (!isShiftedInt<16 , 2 >(Value))
267+ return makeAlignmentError (orc::ExecutorAddr (FixupAddress), Value, 4 , E);
268+
269+ uint32_t RawInstr = *(little32_t *)FixupPtr;
270+ uint32_t Imm = static_cast <uint32_t >(Value >> 2 );
271+ uint32_t Imm15_0 = extractBits (Imm, /* Hi=*/ 15 , /* Lo=*/ 0 ) << 10 ;
272+ *(little32_t *)FixupPtr = RawInstr | Imm15_0;
273+ break ;
274+ }
275+ case Branch21PCRel: {
276+ int64_t Value = TargetAddress - FixupAddress + Addend;
277+
278+ if (!isInt<23 >(Value))
279+ return makeTargetOutOfRangeError (G, B, E);
280+
281+ if (!isShiftedInt<21 , 2 >(Value))
282+ return makeAlignmentError (orc::ExecutorAddr (FixupAddress), Value, 4 , E);
283+
284+ uint32_t RawInstr = *(little32_t *)FixupPtr;
285+ uint32_t Imm = static_cast <uint32_t >(Value >> 2 );
286+ uint32_t Imm15_0 = extractBits (Imm, /* Hi=*/ 15 , /* Lo=*/ 0 ) << 10 ;
287+ uint32_t Imm20_16 = extractBits (Imm, /* Hi=*/ 20 , /* Lo=*/ 16 );
288+ *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm20_16;
289+ break ;
290+ }
216291 case Branch26PCRel: {
217292 int64_t Value = TargetAddress - FixupAddress + Addend;
218293
0 commit comments