Encode `call symbol` -> `auipc ra, %pcrel_hi(symbol); jalr ra, ra, %pcrel_lo(symbol)`.
(
sec: &mut SectionData,
symbol: &str,
current_addr: u64,
symbols: &super::symbol_table::SymbolTable,
section_bases: &std::collections::HashMap<SectionKind, u64>,
relocations:
| 341 | section_name: &str, |
| 342 | symbols: &super::symbol_table::SymbolTable, |
| 343 | ) -> Result<u32, AssemblerError> { |
| 344 | let target_addr = resolve_section_local(target, section_name, symbols) |
| 345 | .ok_or_else(|| AssemblerError::new(format!("undefined label `{target}`")))?; |
| 346 | |
| 347 | let offset = (target_addr as i64) - (site_local as i64); |
| 348 | if offset & 1 != 0 { |
| 349 | return Err(AssemblerError::new(format!( |
| 350 | "jump to `{target}` has odd offset {offset}" |
| 351 | ))); |
| 352 | } |
| 353 | if !(-1_048_576..=1_048_574).contains(&offset) { |
| 354 | return Err(AssemblerError::new(format!( |
| 355 | "jump to `{target}` offset {offset} out of J-type range" |
| 356 | ))); |
| 357 | } |
| 358 | |
| 359 | Ok(RealInstruction::Jal(JalInst::new(rd, offset as i32)).encode()) |
| 360 | } |
| 361 | |
| 362 | fn push_u32(sec: &mut SectionData, word: u32, current_addr: &mut u64) { |
| 363 | sec.push_u32_le(word); |
| 364 | *current_addr += 4; |
| 365 | } |
| 366 | |
| 367 | // --- Pseudo-instruction encoding with symbol relocation --- |
| 368 | |
| 369 | // Split a PC-relative byte offset into (hi20, lo12) for AUIPC+lo pairs. |
| 370 | fn pcrel_split(offset: i64) -> (i32, i32) { |
| 371 | let lo12 = ((offset & 0xFFF) as i32).wrapping_sub(if offset & 0x800 != 0 { 0x1000 } else { 0 }); |
| 372 | let hi20 = ((offset - lo12 as i64) >> 12) as i32; |
no test coverage detected