MCPcopy Create free account
hub / github.com/LPC4/Full-Stack / expand_li

Function expand_li

crates/asm-to-binary/src/pseudo.rs:393–447  ·  view source on GitHub ↗

Expands `li rd, imm` into the minimal real instruction sequence.

(rd: Reg, imm: i64)

Source from the content-addressed store, hash-verified

391 if (-2048..=2047).contains(&imm) {
392 return vec![RealInstruction::Addi(Addi::new(rd, 0, imm as i32))];
393 }
394
395 // 32-bit case: the value must fit into a signed 32-bit word.
396 // If so, we can use lui + addi.
397 let fits_i32 = (-2_147_483_648..=2_147_483_647).contains(&imm);
398 if fits_i32 {
399 let imm32 = imm as i32;
400 let lo12 = imm32 & 0xFFF; // unsigned lower 12 bits
401 let lo12_signed = if lo12 >= 0x800 { lo12 - 0x1000 } else { lo12 };
402 // hi20_val is the value whose upper 20 bits are the lui immediate.
403 let hi20_val = imm32.wrapping_sub(lo12_signed); // hi20_val is a multiple of 0x1000
404 let mut out = vec![RealInstruction::Lui(Lui::new(rd, hi20_val))];
405 if lo12_signed != 0 {
406 out.push(RealInstruction::Addi(Addi::new(rd, rd, lo12_signed)));
407 }
408 return out;
409 }
410
411 // 64-bit case: construct the value from two 32-bit halves.
412 // The expansion uses t1 (x6) as a temporary - it is caller-saved
413 let low32 = (imm & 0xFFFF_FFFF) as i32; // as 32-bit signed
414 let high32 = ((imm >> 32) & 0xFFFF_FFFF) as i32; // as 32-bit signed
415
416 // Helper to produce the lui+addi sequence for a 32-bit constant
417 fn load32(rd: Reg, val32: i32) -> Vec<RealInstruction> {
418 let lo12 = val32 & 0xFFF;
419 let lo12_signed = if lo12 >= 0x800 { lo12 - 0x1000 } else { lo12 };
420 let hi20 = val32.wrapping_sub(lo12_signed);
421 let mut seq = vec![RealInstruction::Lui(Lui::new(rd, hi20))];
422 if lo12_signed != 0 {
423 seq.push(RealInstruction::Addi(Addi::new(rd, rd, lo12_signed)));
424 }
425 seq
426 }
427
428 let mut seq = Vec::new();
429
430 // Load the high 32 bits into t1 and shift them left by 32.
431 seq.append(&mut load32(T1, high32)); // T1 = sign_ext(high32)
432 seq.push(RealInstruction::Slli(Slli::new(T1, T1, 32))); // T1 = high32 << 32
433
434 // Load the low 32 bits into rd, then zero-extend to 64 bits.
435 seq.append(&mut load32(rd, low32)); // rd = sign_ext(low32)
436 seq.push(RealInstruction::Slli(Slli::new(rd, rd, 32))); // clear upper 32 bits
437 seq.push(RealInstruction::Srli(Srli::new(rd, rd, 32))); // rd = zero_ext(low32)
438
439 // Combine: rd = zero_ext(low32) | (high32 << 32)
440 seq.push(RealInstruction::Or(Or::new(rd, rd, T1)));
441
442 seq
443}

Callers 1

expandMethod · 0.70

Calls 5

load32Function · 0.85
SlliClass · 0.85
SrliClass · 0.85
pushMethod · 0.80
containsMethod · 0.45

Tested by

no test coverage detected