1use crate::elf::AllowedRange;
2use crate::elf::LoongArch64Instruction;
3use crate::elf::PAGE_MASK_4KB;
4use crate::elf::PageMask;
5use crate::elf::RelocationKind;
6use crate::elf::RelocationKindInfo;
7use crate::elf::RelocationSize;
8use crate::elf::SIZE_2GB;
9use crate::elf::SIZE_2KB;
10use crate::elf::SIZE_4GB;
11use crate::elf::SIZE_4KB;
12use crate::elf::Sign;
13use crate::relaxation::RelocationModifier;
14use crate::utils::and_from_slice;
15use crate::utils::or_from_slice;
16use crate::utils::u32_from_slice;
17use crate::utils::u64_from_slice;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum RelaxationKind {
21 NoOp,
23
24 ReplaceWithNop,
26}
27
28impl RelaxationKind {
29 pub fn apply(self, section_bytes: &mut [u8], offset_in_section: &mut u64, _addend: &mut i64) {
30 let offset = *offset_in_section as usize;
31 match self {
32 RelaxationKind::NoOp => {}
33 RelaxationKind::ReplaceWithNop => {
34 section_bytes[offset..offset + 4].copy_from_slice(&[
35 0x03, 0x40, 0x0, 0x0, ]);
37 }
38 }
39 }
40
41 #[must_use]
42 pub fn next_modifier(&self) -> RelocationModifier {
43 RelocationModifier::Normal
44 }
45}
46
47#[must_use]
48pub const fn relocation_type_from_raw(r_type: u32) -> Option<RelocationKindInfo> {
49 let (kind, size, mask, range, alignment, bias) = match r_type {
52 object::elf::R_LARCH_NONE => (
53 RelocationKind::None,
54 RelocationSize::ByteSize(0),
55 None,
56 AllowedRange::no_check(),
57 1,
58 0,
59 ),
60 object::elf::R_LARCH_32 => (
62 RelocationKind::Absolute,
63 RelocationSize::ByteSize(4),
64 None,
65 AllowedRange::new(-(2i64.pow(31)), 2i64.pow(32)),
67 1,
68 0,
69 ),
70 object::elf::R_LARCH_64 => (
71 RelocationKind::Absolute,
72 RelocationSize::ByteSize(8),
73 None,
74 AllowedRange::no_check(),
75 1,
76 0,
77 ),
78 object::elf::R_LARCH_ADD6 => (
79 RelocationKind::AbsoluteAdditionWord6,
80 RelocationSize::ByteSize(1),
81 None,
82 AllowedRange::no_check(),
83 1,
84 0,
85 ),
86 object::elf::R_LARCH_ADD8 => (
87 RelocationKind::AbsoluteAddition,
88 RelocationSize::ByteSize(1),
89 None,
90 AllowedRange::no_check(),
91 1,
92 0,
93 ),
94 object::elf::R_LARCH_ADD16 => (
95 RelocationKind::AbsoluteAddition,
96 RelocationSize::ByteSize(2),
97 None,
98 AllowedRange::no_check(),
99 1,
100 0,
101 ),
102 object::elf::R_LARCH_ADD24 => (
103 RelocationKind::AbsoluteAddition,
104 RelocationSize::ByteSize(3),
105 None,
106 AllowedRange::no_check(),
107 1,
108 0,
109 ),
110 object::elf::R_LARCH_ADD32 => (
111 RelocationKind::AbsoluteAddition,
112 RelocationSize::ByteSize(4),
113 None,
114 AllowedRange::no_check(),
115 1,
116 0,
117 ),
118 object::elf::R_LARCH_ADD64 => (
119 RelocationKind::AbsoluteAddition,
120 RelocationSize::ByteSize(8),
121 None,
122 AllowedRange::no_check(),
123 1,
124 0,
125 ),
126 object::elf::R_LARCH_SUB6 => (
127 RelocationKind::AbsoluteSubtractionWord6,
128 RelocationSize::ByteSize(1),
129 None,
130 AllowedRange::no_check(),
131 1,
132 0,
133 ),
134 object::elf::R_LARCH_SUB8 => (
135 RelocationKind::AbsoluteSubtraction,
136 RelocationSize::ByteSize(1),
137 None,
138 AllowedRange::no_check(),
139 1,
140 0,
141 ),
142 object::elf::R_LARCH_SUB16 => (
143 RelocationKind::AbsoluteSubtraction,
144 RelocationSize::ByteSize(2),
145 None,
146 AllowedRange::no_check(),
147 1,
148 0,
149 ),
150 object::elf::R_LARCH_SUB24 => (
151 RelocationKind::AbsoluteSubtraction,
152 RelocationSize::ByteSize(3),
153 None,
154 AllowedRange::no_check(),
155 1,
156 0,
157 ),
158 object::elf::R_LARCH_SUB32 => (
159 RelocationKind::AbsoluteSubtraction,
160 RelocationSize::ByteSize(4),
161 None,
162 AllowedRange::no_check(),
163 1,
164 0,
165 ),
166 object::elf::R_LARCH_SUB64 => (
167 RelocationKind::AbsoluteSubtraction,
168 RelocationSize::ByteSize(8),
169 None,
170 AllowedRange::no_check(),
171 1,
172 0,
173 ),
174 object::elf::R_LARCH_ADD_ULEB128 => (
177 RelocationKind::Relative,
178 RelocationSize::ByteSize(0),
179 None,
180 AllowedRange::no_check(),
181 1,
182 0,
183 ),
184 object::elf::R_LARCH_SUB_ULEB128 => (
185 RelocationKind::PairSubtractionULEB128(object::elf::R_LARCH_ADD_ULEB128),
186 RelocationSize::ByteSize(8),
187 None,
188 AllowedRange::no_check(),
189 1,
190 0,
191 ),
192 object::elf::R_LARCH_ABS_HI20 => (
194 RelocationKind::Absolute,
195 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
196 None,
197 AllowedRange::no_check(),
198 1,
199 0,
200 ),
201 object::elf::R_LARCH_ABS_LO12 => (
202 RelocationKind::Absolute,
203 RelocationSize::bit_mask_loongarch64(0, 12, LoongArch64Instruction::Shift10),
204 None,
205 AllowedRange::no_check(),
206 1,
207 0,
208 ),
209 object::elf::R_LARCH_ABS64_HI12 => (
210 RelocationKind::Absolute,
211 RelocationSize::bit_mask_loongarch64(52, 64, LoongArch64Instruction::Shift10),
212 None,
213 AllowedRange::no_check(),
214 1,
215 0,
216 ),
217 object::elf::R_LARCH_ABS64_LO20 => (
218 RelocationKind::Absolute,
219 RelocationSize::bit_mask_loongarch64(32, 52, LoongArch64Instruction::Shift5),
220 None,
221 AllowedRange::no_check(),
222 1,
223 0,
224 ),
225 object::elf::R_LARCH_PCALA_HI20 => (
226 RelocationKind::Relative,
227 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
228 Some(PageMask::SymbolPlusAddendAndPosition(PAGE_MASK_4KB)),
229 AllowedRange::no_check(),
230 1,
231 SIZE_2KB,
232 ),
233 object::elf::R_LARCH_PCALA_LO12 => (
234 RelocationKind::AbsoluteLowPart,
235 RelocationSize::bit_mask_loongarch64(0, 12, LoongArch64Instruction::Shift10),
236 None,
237 AllowedRange::no_check(),
238 1,
239 0,
240 ),
241 object::elf::R_LARCH_PCALA64_HI12 => (
242 RelocationKind::RelativeLoongArchHigh,
243 RelocationSize::bit_mask_loongarch64(52, 64, LoongArch64Instruction::Shift10),
244 None,
246 AllowedRange::no_check(),
247 1,
248 0,
249 ),
250 object::elf::R_LARCH_PCALA64_LO20 => (
251 RelocationKind::RelativeLoongArchHigh,
252 RelocationSize::bit_mask_loongarch64(32, 52, LoongArch64Instruction::Shift5),
253 None,
255 AllowedRange::no_check(),
256 1,
257 0,
258 ),
259 object::elf::R_LARCH_32_PCREL => (
260 RelocationKind::Relative,
261 RelocationSize::ByteSize(4),
262 None,
263 AllowedRange::from_bit_size(32, Sign::Signed),
265 1,
266 0,
267 ),
268 object::elf::R_LARCH_PCREL20_S2 => (
269 RelocationKind::Relative,
270 RelocationSize::bit_mask_loongarch64(2, 22, LoongArch64Instruction::Shift5),
271 None,
272 AllowedRange::from_bit_size(22, Sign::Signed),
274 4,
275 0,
276 ),
277 object::elf::R_LARCH_64_PCREL => (
278 RelocationKind::Relative,
279 RelocationSize::ByteSize(8),
280 None,
281 AllowedRange::no_check(),
282 1,
283 0,
284 ),
285 object::elf::R_LARCH_PCADD_HI20 => (
286 RelocationKind::Relative,
287 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
288 None,
289 AllowedRange::no_check(),
290 1,
291 SIZE_2KB,
292 ),
293 object::elf::R_LARCH_GOT_PC_HI20 => (
295 RelocationKind::GotRelative,
296 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
297 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
298 AllowedRange::no_check(),
299 1,
300 SIZE_2KB,
301 ),
302 object::elf::R_LARCH_GOT_PC_LO12 => (
303 RelocationKind::Got,
304 RelocationSize::bit_mask_loongarch64(0, 12, LoongArch64Instruction::Shift10),
305 None,
306 AllowedRange::no_check(),
307 1,
308 0,
309 ),
310 object::elf::R_LARCH_GOT64_PC_HI12 => (
311 RelocationKind::GotRelativeLoongArch64,
312 RelocationSize::bit_mask_loongarch64(52, 64, LoongArch64Instruction::Shift10),
313 None,
315 AllowedRange::no_check(),
316 1,
317 0,
318 ),
319 object::elf::R_LARCH_GOT64_PC_LO20 => (
320 RelocationKind::GotRelativeLoongArch64,
321 RelocationSize::bit_mask_loongarch64(32, 52, LoongArch64Instruction::Shift5),
322 None,
324 AllowedRange::no_check(),
325 1,
326 0,
327 ),
328 object::elf::R_LARCH_B16 => (
330 RelocationKind::Relative,
331 RelocationSize::bit_mask_loongarch64(2, 18, LoongArch64Instruction::Shift10),
332 None,
333 AllowedRange::from_bit_size(18, Sign::Signed),
335 4,
336 0,
337 ),
338 object::elf::R_LARCH_B21 => (
339 RelocationKind::Relative,
340 RelocationSize::bit_mask_loongarch64(2, 23, LoongArch64Instruction::Branch21),
341 None,
342 AllowedRange::from_bit_size(23, Sign::Signed),
344 4,
345 0,
346 ),
347 object::elf::R_LARCH_B26 => (
348 RelocationKind::PltRelative,
349 RelocationSize::bit_mask_loongarch64(2, 28, LoongArch64Instruction::Branch26),
350 None,
351 AllowedRange::from_bit_size(28, Sign::Signed),
353 4,
354 0,
355 ),
356 object::elf::R_LARCH_CALL36 => (
357 RelocationKind::Relative,
358 RelocationSize::bit_mask_loongarch64(2, 38, LoongArch64Instruction::Call36),
359 None,
360 AllowedRange::from_bit_size(38, Sign::Signed),
362 4,
363 0,
364 ),
365 object::elf::R_LARCH_CALL30 => (
366 RelocationKind::Relative,
367 RelocationSize::bit_mask_loongarch64(2, 19, LoongArch64Instruction::Call30),
368 None,
369 AllowedRange::no_check(),
370 1,
371 0,
372 ),
373 object::elf::R_LARCH_TLS_LE_HI20 => (
375 RelocationKind::TpOff,
376 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
377 None,
378 AllowedRange::no_check(),
379 1,
380 0,
381 ),
382 object::elf::R_LARCH_TLS_LE_LO12 => (
383 RelocationKind::TpOff,
384 RelocationSize::bit_mask_loongarch64(0, 12, LoongArch64Instruction::Shift10),
385 None,
386 AllowedRange::no_check(),
387 1,
388 0,
389 ),
390 object::elf::R_LARCH_TLS_LE64_LO20 => (
391 RelocationKind::TpOff,
392 RelocationSize::bit_mask_loongarch64(32, 52, LoongArch64Instruction::Shift5),
393 None,
394 AllowedRange::no_check(),
395 1,
396 0,
397 ),
398 object::elf::R_LARCH_TLS_LE64_HI12 => (
399 RelocationKind::TpOff,
400 RelocationSize::bit_mask_loongarch64(52, 64, LoongArch64Instruction::Shift10),
401 None,
402 AllowedRange::no_check(),
403 1,
404 0,
405 ),
406 object::elf::R_LARCH_TLS_LE_HI20_R => (
407 RelocationKind::TpOff,
408 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
409 None,
410 AllowedRange::no_check(),
411 1,
412 SIZE_2KB,
413 ),
414 object::elf::R_LARCH_TLS_LE_LO12_R => (
415 RelocationKind::TpOff,
416 RelocationSize::bit_mask_loongarch64(0, 12, LoongArch64Instruction::Shift10),
417 None,
418 AllowedRange::no_check(),
419 1,
420 0,
421 ),
422 object::elf::R_LARCH_TLS_IE_PC_HI20 => (
423 RelocationKind::GotTpOff,
424 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
425 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
426 AllowedRange::no_check(),
427 1,
428 SIZE_2KB,
429 ),
430 object::elf::R_LARCH_TLS_IE_PC_LO12 => (
431 RelocationKind::GotTpOffGot,
432 RelocationSize::bit_mask_loongarch64(0, 12, LoongArch64Instruction::Shift10),
433 None,
434 AllowedRange::no_check(),
435 1,
436 0,
437 ),
438 object::elf::R_LARCH_TLS_IE64_PC_LO20 => (
439 RelocationKind::GotTpOffLoongArch64,
440 RelocationSize::bit_mask_loongarch64(32, 52, LoongArch64Instruction::Shift5),
441 None,
443 AllowedRange::no_check(),
444 1,
445 0,
446 ),
447 object::elf::R_LARCH_TLS_IE64_PC_HI12 => (
448 RelocationKind::GotTpOffLoongArch64,
449 RelocationSize::bit_mask_loongarch64(52, 64, LoongArch64Instruction::Shift10),
450 None,
452 AllowedRange::no_check(),
453 1,
454 0,
455 ),
456 object::elf::R_LARCH_TLS_IE_HI20 => (
457 RelocationKind::GotTpOffGot,
458 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
459 None,
460 AllowedRange::no_check(),
461 1,
462 0,
463 ),
464 object::elf::R_LARCH_TLS_IE_LO12 => (
465 RelocationKind::GotTpOffGot,
466 RelocationSize::bit_mask_loongarch64(0, 12, LoongArch64Instruction::Shift10),
467 None,
468 AllowedRange::no_check(),
469 1,
470 0,
471 ),
472 object::elf::R_LARCH_TLS_IE64_HI12 => (
473 RelocationKind::GotTpOffGot,
474 RelocationSize::bit_mask_loongarch64(52, 64, LoongArch64Instruction::Shift10),
475 None,
476 AllowedRange::no_check(),
477 1,
478 0,
479 ),
480 object::elf::R_LARCH_TLS_IE64_LO20 => (
481 RelocationKind::GotTpOffGot,
482 RelocationSize::bit_mask_loongarch64(32, 52, LoongArch64Instruction::Shift5),
483 None,
484 AllowedRange::no_check(),
485 1,
486 0,
487 ),
488 object::elf::R_LARCH_TLS_LD_PC_HI20 => (
491 RelocationKind::TlsGd,
492 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
493 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
494 AllowedRange::no_check(),
495 1,
496 SIZE_2KB,
497 ),
498 object::elf::R_LARCH_TLS_LD_HI20 => (
499 RelocationKind::TlsGdGot,
500 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
501 None,
502 AllowedRange::no_check(),
503 1,
504 0,
505 ),
506 object::elf::R_LARCH_TLS_GD_PC_HI20 => (
507 RelocationKind::TlsGd,
508 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
509 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
510 AllowedRange::no_check(),
511 1,
512 SIZE_2KB,
513 ),
514 object::elf::R_LARCH_TLS_GD_HI20 => (
515 RelocationKind::TlsGdGot,
516 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
517 None,
518 AllowedRange::no_check(),
519 1,
520 0,
521 ),
522 object::elf::R_LARCH_TLS_DESC_PC_HI20 => (
524 RelocationKind::TlsDesc,
525 RelocationSize::bit_mask_loongarch64(12, 32, LoongArch64Instruction::Shift5),
526 Some(PageMask::GotEntryAndPosition(PAGE_MASK_4KB)),
527 AllowedRange::no_check(),
528 1,
529 SIZE_2KB,
530 ),
531 object::elf::R_LARCH_TLS_DESC_PC_LO12 => (
532 RelocationKind::TlsDescGot,
533 RelocationSize::bit_mask_loongarch64(0, 12, LoongArch64Instruction::Shift10),
534 None,
535 AllowedRange::no_check(),
536 1,
537 0,
538 ),
539 object::elf::R_LARCH_TLS_DESC64_PC_HI12 => (
540 RelocationKind::TlsDescLoongArch64,
541 RelocationSize::bit_mask_loongarch64(52, 64, LoongArch64Instruction::Shift10),
542 None,
544 AllowedRange::no_check(),
545 1,
546 0,
547 ),
548 object::elf::R_LARCH_TLS_DESC64_PC_LO20 => (
549 RelocationKind::TlsDescLoongArch64,
550 RelocationSize::bit_mask_loongarch64(32, 52, LoongArch64Instruction::Shift5),
551 None,
553 AllowedRange::no_check(),
554 1,
555 0,
556 ),
557 object::elf::R_LARCH_TLS_DESC_LD => (
558 RelocationKind::None,
559 RelocationSize::ByteSize(0),
560 None,
561 AllowedRange::no_check(),
562 1,
563 0,
564 ),
565 object::elf::R_LARCH_TLS_DESC_CALL => (
566 RelocationKind::TlsDescCall,
567 RelocationSize::ByteSize(0),
568 None,
569 AllowedRange::no_check(),
570 1,
571 0,
572 ),
573 object::elf::R_LARCH_TLS_DTPREL32 => (
575 RelocationKind::DtpOff,
576 RelocationSize::ByteSize(4),
577 None,
578 AllowedRange::no_check(),
579 1,
580 0,
581 ),
582 object::elf::R_LARCH_TLS_DTPREL64 => (
583 RelocationKind::DtpOff,
584 RelocationSize::ByteSize(8),
585 None,
586 AllowedRange::no_check(),
587 1,
588 0,
589 ),
590 object::elf::R_LARCH_TLS_LD_PCREL20_S2
592 | object::elf::R_LARCH_TLS_GD_PCREL20_S2
593 | object::elf::R_LARCH_TLS_DESC_PCREL20_S2 => {
594 return None;
595 }
596 object::elf::R_LARCH_RELAX | object::elf::R_LARCH_TLS_LE_ADD_R => (
598 RelocationKind::None,
599 RelocationSize::ByteSize(0),
600 None,
601 AllowedRange::no_check(),
602 1,
603 0,
604 ),
605 object::elf::R_LARCH_ALIGN => (
606 RelocationKind::None,
607 RelocationSize::ByteSize(0),
608 None,
609 AllowedRange::no_check(),
610 1,
611 0,
612 ),
613 _ => return None,
614 };
615
616 Some(RelocationKindInfo {
617 kind,
618 size,
619 mask,
620 range,
621 alignment,
622 bias,
623 thunkable: false,
624 })
625}
626
627impl LoongArch64Instruction {
628 pub fn write_to_value(self, extracted_value: u64, _negative: bool, dest: &mut [u8]) {
629 match self {
630 LoongArch64Instruction::Shift5 => {
631 and_from_slice(dest, &0xFE00_001F_u32.to_le_bytes());
633 let mask = extracted_value << 5;
634 or_from_slice(dest, &(mask as u32).to_le_bytes());
635 }
636 LoongArch64Instruction::Shift10 => {
637 and_from_slice(dest, &0xFFC0_03FF_u32.to_le_bytes());
639 let mask = extracted_value << 10;
640 or_from_slice(dest, &(mask as u32).to_le_bytes());
641 }
642 LoongArch64Instruction::Branch26 => {
643 and_from_slice(dest, &0xFC00_0000_u32.to_le_bytes());
645 let low_part = (extracted_value & 0xffff) << 10;
646 let high_part = extracted_value >> 16;
647 or_from_slice(dest, &((low_part | high_part) as u32).to_le_bytes());
648 }
649 LoongArch64Instruction::Branch21 => {
650 and_from_slice(dest, &0xFC00_03E0_u32.to_le_bytes());
652 let low_part = (extracted_value & 0xffff) << 10;
653 let high_part = extracted_value >> 16;
654 or_from_slice(dest, &((low_part | high_part) as u32).to_le_bytes());
655 }
656 LoongArch64Instruction::Call30 => {
657 const CLEAR: u64 = (0xFFF8_03FF_u64 << 32) | 0xFE00_001F_u64;
661 and_from_slice(dest, &CLEAR.to_le_bytes());
662 let low_part = (extracted_value & 0x1ff) << (32 + 10);
663 let high_part = (extracted_value & !0x1ff) << 5;
664 or_from_slice(dest, &(low_part | high_part).to_le_bytes());
665 }
666 LoongArch64Instruction::Call36 => {
667 const CLEAR: u64 = (0xFC00_03FF_u64 << 32) | 0xFE00_001F_u64;
671 and_from_slice(dest, &CLEAR.to_le_bytes());
672 let low_part = (extracted_value & 0xffff) << (32 + 10);
673 let high_part = ((extracted_value + 0x8000) >> 16) << 5;
674 or_from_slice(dest, &(low_part | high_part).to_le_bytes());
675 }
676 };
677 }
678
679 #[must_use]
680 pub fn read_value(self, bytes: &[u8]) -> (u64, bool) {
681 match self {
682 LoongArch64Instruction::Shift5 => {
683 let value = u32_from_slice(bytes);
685 let imm = (value >> 5) & 0xfffff;
686
687 (u64::from(imm), false)
688 }
689 LoongArch64Instruction::Shift10 => {
690 let value = u32_from_slice(bytes);
692 let imm = (value >> 10) & 0xfff;
693
694 (u64::from(imm), false)
695 }
696 LoongArch64Instruction::Branch26 => {
697 let value = u32_from_slice(bytes);
699 let low_part = (value >> 10) & 0xffff;
700 let high_part = value & 0x3ff;
701 let imm = (high_part << 16) | low_part;
702 let sign_extended = ((imm as i32) << 6) >> 6;
704
705 (sign_extended as u64, sign_extended < 0)
706 }
707 LoongArch64Instruction::Branch21 => {
708 let value = u32_from_slice(bytes);
710 let low_part = (value >> 10) & 0xffff;
711 let high_part = value & 0x1f;
712 let imm = (high_part << 16) | low_part;
713 let sign_extended = ((imm as i32) << 11) >> 11;
715
716 (sign_extended as u64, sign_extended < 0)
717 }
718 LoongArch64Instruction::Call30 => {
719 let value = u64_from_slice(bytes);
723 let insn1 = (value >> 32) as u32;
724 let insn2 = value as u32;
725 let high_part = ((insn1 >> 5) & 0x7ffff) << 9; let low_part = (insn2 >> 10) & 0x1ff;
727 let imm = high_part | low_part;
728
729 (u64::from(imm), false)
730 }
731 LoongArch64Instruction::Call36 => {
732 let value = u64_from_slice(bytes);
736 let insn1 = value as u32;
737 let insn2 = (value >> 32) as u32;
738 let high_part = u64::from((insn1 >> 5) & 0xfffff);
739 let low_part = u64::from((insn2 >> 10) & 0xffff);
740 let imm = ((high_part << 16).wrapping_sub(0x8000) & 0xffffffff) | low_part;
744
745 (imm, false)
746 }
747 }
748 }
749}
750
751#[must_use]
755pub fn highest_relocation_with_bias(symbol_with_addend: u64, pc: u64) -> u64 {
756 ((symbol_with_addend.wrapping_add(SIZE_2GB).wrapping_add(
757 if symbol_with_addend & SIZE_2KB != 0 {
758 SIZE_4KB.wrapping_sub(SIZE_4GB)
759 } else {
760 0
761 },
762 )) & !PAGE_MASK_4KB)
763 .wrapping_sub((pc.wrapping_sub(8)) & !PAGE_MASK_4KB)
764}