From f3d500eb94ce497bc3a32b8948b9a6a58a48a61c Mon Sep 17 00:00:00 2001 From: Rajesh Gangam Date: Wed, 1 Jul 2026 18:37:32 +0530 Subject: [PATCH] riscv64: Split clobber save/restore SP adjustment for compressed instructions When the Zca extension is enabled, split the SP adjustment in function prologues/epilogues so callee-saved stores use small SP-relative offsets that fit in c.sdsp's 504-byte encoding range. This allows all callee-save stores/loads to compress from 4-byte sd/ld to 2-byte c.sdsp/c.ldsp. Without Zca, the original combined SP decrement is preserved to avoid adding an extra instruction with no compression benefit. Also adds isa_flags parameter to the ABIMachineSpec gen_clobber_save and gen_clobber_restore trait methods so implementations can make ISA-specific decisions. Fixes #7190. --- cranelift/codegen/src/isa/aarch64/abi.rs | 2 + .../codegen/src/isa/aarch64/inst/emit.rs | 1 + .../codegen/src/isa/pulley_shared/abi.rs | 2 + cranelift/codegen/src/isa/riscv64/abi.rs | 122 +++-- cranelift/codegen/src/isa/s390x/abi.rs | 2 + cranelift/codegen/src/isa/x64/abi.rs | 2 + cranelift/codegen/src/isa/x64/inst/emit.rs | 9 +- cranelift/codegen/src/machinst/abi.rs | 4 + .../isa/riscv64/c-clobber-save-restore.clif | 452 ++++++++++++++++++ 9 files changed, 550 insertions(+), 46 deletions(-) create mode 100644 cranelift/filetests/filetests/isa/riscv64/c-clobber-save-restore.clif diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs index 806ad1566a92..b35a49d0fa88 100644 --- a/cranelift/codegen/src/isa/aarch64/abi.rs +++ b/cranelift/codegen/src/isa/aarch64/abi.rs @@ -774,6 +774,7 @@ impl ABIMachineSpec for AArch64MachineDeps { fn gen_clobber_save( call_conv: isa::CallConv, flags: &settings::Flags, + _isa_flags: &aarch64_settings::Flags, frame_layout: &FrameLayout, ) -> SmallVec<[Inst; 16]> { let (clobbered_int, clobbered_vec) = frame_layout.clobbered_callee_saves_by_class(); @@ -1020,6 +1021,7 @@ impl ABIMachineSpec for AArch64MachineDeps { fn gen_clobber_restore( call_conv: isa::CallConv, _flags: &settings::Flags, + _isa_flags: &aarch64_settings::Flags, frame_layout: &FrameLayout, ) -> SmallVec<[Inst; 16]> { let mut insts = SmallVec::new(); diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 0c261c267e56..9e88d13aec16 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -3661,6 +3661,7 @@ fn emit_return_call_common_sequence( for inst in AArch64MachineDeps::gen_clobber_restore( CallConv::Tail, &emit_info.flags, + &emit_info.isa_flags, state.frame_layout(), ) { inst.emit(sink, emit_info, state); diff --git a/cranelift/codegen/src/isa/pulley_shared/abi.rs b/cranelift/codegen/src/isa/pulley_shared/abi.rs index e077ef04a3f8..1339d90a3ea0 100644 --- a/cranelift/codegen/src/isa/pulley_shared/abi.rs +++ b/cranelift/codegen/src/isa/pulley_shared/abi.rs @@ -433,6 +433,7 @@ where fn gen_clobber_save( _call_conv: isa::CallConv, _flags: &settings::Flags, + _isa_flags: &PulleyFlags, _frame_layout: &FrameLayout, ) -> SmallVec<[Self::I; 16]> { // Note that this is intentionally empty because everything necessary @@ -443,6 +444,7 @@ where fn gen_clobber_restore( _call_conv: isa::CallConv, _flags: &settings::Flags, + _isa_flags: &PulleyFlags, _frame_layout: &FrameLayout, ) -> SmallVec<[Self::I; 16]> { // Intentionally empty as restores happen for Pulley in `gen_return`. diff --git a/cranelift/codegen/src/isa/riscv64/abi.rs b/cranelift/codegen/src/isa/riscv64/abi.rs index ab815bbdf952..8256d7eedd97 100644 --- a/cranelift/codegen/src/isa/riscv64/abi.rs +++ b/cranelift/codegen/src/isa/riscv64/abi.rs @@ -431,6 +431,7 @@ impl ABIMachineSpec for Riscv64MachineDeps { fn gen_clobber_save( _call_conv: isa::CallConv, flags: &settings::Flags, + isa_flags: &RiscvFlags, frame_layout: &FrameLayout, ) -> SmallVec<[Inst; 16]> { let mut insts = SmallVec::new(); @@ -479,61 +480,91 @@ impl ABIMachineSpec for Riscv64MachineDeps { }); } - // Adjust the stack pointer downward for clobbers, the function fixed - // frame (spillslots and storage slots), and outgoing arguments. - let stack_size = frame_layout.clobber_size - + frame_layout.fixed_frame_storage_size - + frame_layout.outgoing_args_size; - - // Store each clobbered register in order at offsets from SP, - // placing them above the fixed frame slots. - if stack_size > 0 { - insts.extend(Self::gen_sp_reg_adjust(-(stack_size as i32))); - - let mut cur_offset = 0; - for reg in &frame_layout.clobbered_callee_saves { - let r_reg = reg.to_reg(); - let ty = match r_reg.class() { - RegClass::Int => I64, - RegClass::Float => F64, - RegClass::Vector => I8X16, - }; - cur_offset = align_to(cur_offset, ty.bytes()); - insts.push(Inst::gen_store( - AMode::SPOffset(i64::from(stack_size - cur_offset - ty.bytes())), - Reg::from(reg.to_reg()), - ty, - MemFlagsData::trusted(), - )); + let clobber_size = frame_layout.clobber_size; + let remaining_frame_size = + frame_layout.fixed_frame_storage_size + frame_layout.outgoing_args_size; - if flags.unwind_info() { - insts.push(Inst::Unwind { - inst: UnwindInst::SaveReg { - clobber_offset: frame_layout.clobber_size - cur_offset - ty.bytes(), - reg: r_reg, - }, - }); - } + // When the Zca extension is available, split the SP adjustment so + // callee-save stores use small offsets that fit in c.sdsp (≤504 bytes). + // Without Zca, use a single combined decrement to avoid an extra instruction. + let split_adjustment = isa_flags.has_zca() && clobber_size > 0 && remaining_frame_size > 0; + + if split_adjustment { + insts.extend(Self::gen_sp_reg_adjust(-(clobber_size as i32))); + } else { + let stack_size = clobber_size + remaining_frame_size; + if stack_size > 0 { + insts.extend(Self::gen_sp_reg_adjust(-(stack_size as i32))); + } + } + + let store_base = if split_adjustment { + clobber_size + } else { + clobber_size + remaining_frame_size + }; + + let mut cur_offset = 0; + for reg in &frame_layout.clobbered_callee_saves { + let r_reg = reg.to_reg(); + let ty = match r_reg.class() { + RegClass::Int => I64, + RegClass::Float => F64, + RegClass::Vector => I8X16, + }; + cur_offset = align_to(cur_offset, ty.bytes()); + insts.push(Inst::gen_store( + AMode::SPOffset(i64::from(store_base - cur_offset - ty.bytes())), + Reg::from(reg.to_reg()), + ty, + MemFlagsData::trusted(), + )); - cur_offset += ty.bytes(); - assert!(cur_offset <= stack_size); + if flags.unwind_info() { + insts.push(Inst::Unwind { + inst: UnwindInst::SaveReg { + clobber_offset: clobber_size - cur_offset - ty.bytes(), + reg: r_reg, + }, + }); } + + cur_offset += ty.bytes(); + assert!(cur_offset <= clobber_size); } + + if split_adjustment { + insts.extend(Self::gen_sp_reg_adjust(-(remaining_frame_size as i32))); + } + insts } fn gen_clobber_restore( _call_conv: isa::CallConv, _flags: &settings::Flags, + isa_flags: &RiscvFlags, frame_layout: &FrameLayout, ) -> SmallVec<[Inst; 16]> { let mut insts = SmallVec::new(); - let stack_size = frame_layout.clobber_size - + frame_layout.fixed_frame_storage_size - + frame_layout.outgoing_args_size; - let mut cur_offset = 0; + let clobber_size = frame_layout.clobber_size; + let remaining_frame_size = + frame_layout.fixed_frame_storage_size + frame_layout.outgoing_args_size; + + let split_adjustment = isa_flags.has_zca() && clobber_size > 0 && remaining_frame_size > 0; + if split_adjustment { + insts.extend(Self::gen_sp_reg_adjust(remaining_frame_size as i32)); + } + + let load_base = if split_adjustment { + clobber_size + } else { + clobber_size + remaining_frame_size + }; + + let mut cur_offset = 0; for reg in &frame_layout.clobbered_callee_saves { let rreg = reg.to_reg(); let ty = match rreg.class() { @@ -544,15 +575,20 @@ impl ABIMachineSpec for Riscv64MachineDeps { cur_offset = align_to(cur_offset, ty.bytes()); insts.push(Inst::gen_load( reg.map(Reg::from), - AMode::SPOffset(i64::from(stack_size - cur_offset - ty.bytes())), + AMode::SPOffset(i64::from(load_base - cur_offset - ty.bytes())), ty, MemFlagsData::trusted(), )); cur_offset += ty.bytes(); } - if stack_size > 0 { - insts.extend(Self::gen_sp_reg_adjust(stack_size as i32)); + let restore_size = if split_adjustment { + clobber_size + } else { + clobber_size + remaining_frame_size + }; + if restore_size > 0 { + insts.extend(Self::gen_sp_reg_adjust(restore_size as i32)); } insts diff --git a/cranelift/codegen/src/isa/s390x/abi.rs b/cranelift/codegen/src/isa/s390x/abi.rs index 42bbe3d23d99..fd8fce5e5937 100644 --- a/cranelift/codegen/src/isa/s390x/abi.rs +++ b/cranelift/codegen/src/isa/s390x/abi.rs @@ -698,6 +698,7 @@ impl ABIMachineSpec for S390xMachineDeps { fn gen_clobber_save( call_conv: isa::CallConv, flags: &settings::Flags, + _isa_flags: &s390x_settings::Flags, frame_layout: &FrameLayout, ) -> SmallVec<[Inst; 16]> { let mut insts = SmallVec::new(); @@ -860,6 +861,7 @@ impl ABIMachineSpec for S390xMachineDeps { fn gen_clobber_restore( call_conv: isa::CallConv, _flags: &settings::Flags, + _isa_flags: &s390x_settings::Flags, frame_layout: &FrameLayout, ) -> SmallVec<[Inst; 16]> { let mut insts = SmallVec::new(); diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs index 7961044fb117..360af674b7e2 100644 --- a/cranelift/codegen/src/isa/x64/abi.rs +++ b/cranelift/codegen/src/isa/x64/abi.rs @@ -653,6 +653,7 @@ impl ABIMachineSpec for X64ABIMachineSpec { fn gen_clobber_save( _call_conv: isa::CallConv, flags: &settings::Flags, + _isa_flags: &x64_settings::Flags, frame_layout: &FrameLayout, ) -> SmallVec<[Self::I; 16]> { let mut insts = SmallVec::new(); @@ -764,6 +765,7 @@ impl ABIMachineSpec for X64ABIMachineSpec { fn gen_clobber_restore( _call_conv: isa::CallConv, _flags: &settings::Flags, + _isa_flags: &x64_settings::Flags, frame_layout: &FrameLayout, ) -> SmallVec<[Self::I; 16]> { let mut insts = SmallVec::new(); diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index 7f6f1aeb763d..3abe8ddb41a7 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -1879,9 +1879,12 @@ fn emit_return_call_common_sequence( let tmp = call_info.tmp.to_writable_reg(); - for inst in - X64ABIMachineSpec::gen_clobber_restore(CallConv::Tail, &info.flags, state.frame_layout()) - { + for inst in X64ABIMachineSpec::gen_clobber_restore( + CallConv::Tail, + &info.flags, + &info.isa_flags, + state.frame_layout(), + ) { inst.emit(sink, info, state); } diff --git a/cranelift/codegen/src/machinst/abi.rs b/cranelift/codegen/src/machinst/abi.rs index e467d8ccadac..662b07822311 100644 --- a/cranelift/codegen/src/machinst/abi.rs +++ b/cranelift/codegen/src/machinst/abi.rs @@ -542,6 +542,7 @@ pub trait ABIMachineSpec { fn gen_clobber_save( call_conv: isa::CallConv, flags: &settings::Flags, + isa_flags: &Self::F, frame_layout: &FrameLayout, ) -> SmallVec<[Self::I; 16]>; @@ -552,6 +553,7 @@ pub trait ABIMachineSpec { fn gen_clobber_restore( call_conv: isa::CallConv, flags: &settings::Flags, + isa_flags: &Self::F, frame_layout: &FrameLayout, ) -> SmallVec<[Self::I; 16]>; @@ -2287,6 +2289,7 @@ impl Callee { insts.extend(M::gen_clobber_save( self.call_conv, &self.flags, + &self.isa_flags, &frame_layout, )); @@ -2306,6 +2309,7 @@ impl Callee { insts.extend(M::gen_clobber_restore( self.call_conv, &self.flags, + &self.isa_flags, &frame_layout, )); diff --git a/cranelift/filetests/filetests/isa/riscv64/c-clobber-save-restore.clif b/cranelift/filetests/filetests/isa/riscv64/c-clobber-save-restore.clif new file mode 100644 index 000000000000..2febb2466cbb --- /dev/null +++ b/cranelift/filetests/filetests/isa/riscv64/c-clobber-save-restore.clif @@ -0,0 +1,452 @@ +test compile precise-output +set unwind_info=false +target riscv64 has_c + +;; Tests that the split SP adjustment in clobber save/restore keeps +;; callee-save store offsets within c.sdsp's 504-byte encoding limit. +;; +;; Without the split, a single SP decrement of (clobber_size + frame_size) +;; would place callee-save stores at offsets >= frame_size from SP — +;; well beyond 504 bytes for any non-trivial frame — falling back to +;; uncompressed 4-byte sd/ld instructions. +;; +;; With the split, SP is first decremented by clobber_size alone, stores +;; go at offsets 0..clobber_size (always ≤ 504), then a second decrement +;; allocates the remaining frame. All stores compress to 2-byte c.sdsp. + +;; Case 1: Large frame (100KB). Without the split, callee-save offsets +;; would start at ~100000. With the split, offsets are 0-56. +function %large_frame(i64, i64, i64, i64, i64, i64, i64, i64) -> i64 system_v { + fn0 = colocated %external_call() -> i64 system_v +ss0 = explicit_slot 100000 + +block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64): + v8 = call fn0() + v9 = iadd v0, v1 + v10 = iadd v9, v2 + v11 = iadd v10, v3 + v12 = iadd v11, v4 + v13 = iadd v12, v5 + v14 = iadd v13, v6 + v15 = iadd v14, v7 + v16 = iadd v15, v8 + return v16 +} + +; VCode: +; addi sp,sp,-16 +; sd ra,8(sp) +; sd fp,0(sp) +; mv fp,sp +; addi sp,sp,-64 +; sd s1,56(sp) +; sd s2,48(sp) +; sd s3,40(sp) +; sd s4,32(sp) +; sd s5,24(sp) +; sd s6,16(sp) +; sd s8,8(sp) +; sd s10,0(sp) +; lui t6,-24 +; addi t6,t6,-1696 +; add sp,sp,t6 +; block0: +; mv s1,a2 +; mv s2,a7 +; mv s3,a1 +; mv s4,a6 +; mv s5,a0 +; mv s6,a5 +; mv s8,a4 +; mv s10,a3 +; call %external_call +; mv a1,s3 +; mv t0,a0 +; mv a0,s5 +; add a0,a0,a1 +; mv a2,s1 +; add a0,a0,a2 +; mv a3,s10 +; add a0,a0,a3 +; mv a4,s8 +; add a0,a0,a4 +; mv a5,s6 +; add a0,a0,a5 +; mv a6,s4 +; add a0,a0,a6 +; mv a7,s2 +; add a0,a0,a7 +; mv a1,t0 +; add a0,a0,a1 +; lui t6,24 +; addi t6,t6,1696 +; add sp,sp,t6 +; ld s1,56(sp) +; ld s2,48(sp) +; ld s3,40(sp) +; ld s4,32(sp) +; ld s5,24(sp) +; ld s6,16(sp) +; ld s8,8(sp) +; ld s10,0(sp) +; addi sp,sp,64 +; ld ra,8(sp) +; ld fp,0(sp) +; addi sp,sp,16 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; c.addi16sp sp, -0x10 +; c.sdsp ra, 8(sp) +; c.sdsp s0, 0(sp) +; c.mv s0, sp +; c.addi16sp sp, -0x40 +; c.sdsp s1, 0x38(sp) +; c.sdsp s2, 0x30(sp) +; c.sdsp s3, 0x28(sp) +; c.sdsp s4, 0x20(sp) +; c.sdsp s5, 0x18(sp) +; c.sdsp s6, 0x10(sp) +; c.sdsp s8, 8(sp) +; c.sdsp s10, 0(sp) +; c.lui t6, 0xfffe8 +; addi t6, t6, -0x6a0 +; c.add sp, t6 +; block1: ; offset 0x22 +; c.mv s1, a2 +; c.mv s2, a7 +; c.mv s3, a1 +; c.mv s4, a6 +; c.mv s5, a0 +; c.mv s6, a5 +; c.mv s8, a4 +; c.mv s10, a3 +; auipc ra, 0 ; reloc_external RiscvCallPlt %external_call 0 +; jalr ra +; c.mv a1, s3 +; c.mv t0, a0 +; c.mv a0, s5 +; c.add a0, a1 +; c.mv a2, s1 +; c.add a0, a2 +; c.mv a3, s10 +; c.add a0, a3 +; c.mv a4, s8 +; c.add a0, a4 +; c.mv a5, s6 +; c.add a0, a5 +; c.mv a6, s4 +; c.add a0, a6 +; c.mv a7, s2 +; c.add a0, a7 +; c.mv a1, t0 +; c.add a0, a1 +; c.lui t6, 0x18 +; addi t6, t6, 0x6a0 +; c.add sp, t6 +; c.ldsp s1, 0x38(sp) +; c.ldsp s2, 0x30(sp) +; c.ldsp s3, 0x28(sp) +; c.ldsp s4, 0x20(sp) +; c.ldsp s5, 0x18(sp) +; c.ldsp s6, 0x10(sp) +; c.ldsp s8, 8(sp) +; c.ldsp s10, 0(sp) +; c.addi16sp sp, 0x40 +; c.ldsp ra, 8(sp) +; c.ldsp s0, 0(sp) +; c.addi16sp sp, 0x10 +; c.jr ra + +;; Case 2: Minimal frame just over 504 bytes (512). Even a small +;; overshoot prevents c.sdsp without the split. +function %just_over_limit(i64, i64) -> i64 system_v { + fn0 = colocated %external_call() -> i64 system_v +ss0 = explicit_slot 512 + +block0(v0: i64, v1: i64): + v2 = call fn0() + v3 = iadd v0, v1 + v4 = iadd v3, v2 + return v4 +} + +; VCode: +; addi sp,sp,-16 +; sd ra,8(sp) +; sd fp,0(sp) +; mv fp,sp +; addi sp,sp,-16 +; sd s1,8(sp) +; sd s2,0(sp) +; addi sp,sp,-512 +; block0: +; mv s1,a1 +; mv s2,a0 +; call %external_call +; mv a1,s2 +; mv a2,s1 +; add a1,a1,a2 +; add a0,a1,a0 +; addi sp,sp,512 +; ld s1,8(sp) +; ld s2,0(sp) +; addi sp,sp,16 +; ld ra,8(sp) +; ld fp,0(sp) +; addi sp,sp,16 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; c.addi16sp sp, -0x10 +; c.sdsp ra, 8(sp) +; c.sdsp s0, 0(sp) +; c.mv s0, sp +; c.addi16sp sp, -0x10 +; c.sdsp s1, 8(sp) +; c.sdsp s2, 0(sp) +; c.addi16sp sp, -0x200 +; block1: ; offset 0x10 +; c.mv s1, a1 +; c.mv s2, a0 +; auipc ra, 0 ; reloc_external RiscvCallPlt %external_call 0 +; jalr ra +; c.mv a1, s2 +; c.mv a2, s1 +; c.add a1, a2 +; c.add a0, a1 +; addi sp, sp, 0x200 +; c.ldsp s1, 8(sp) +; c.ldsp s2, 0(sp) +; c.addi16sp sp, 0x10 +; c.ldsp ra, 8(sp) +; c.ldsp s0, 0(sp) +; c.addi16sp sp, 0x10 +; c.jr ra + +;; Case 3: Maximum callee-saved registers (all s1-s11 + float fs0-fs11) +;; with a large frame, to stress the split with the widest clobber area. +function %max_clobbers(i64, i64, i64, i64, i64, i64, i64, i64) -> i64 system_v { + fn0 = colocated %use_all(f64, f64, f64, f64, f64, f64, f64, f64, f64, f64, f64) -> i64 system_v +ss0 = explicit_slot 4096 + +block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64): + v8 = f64const 0x1.0 + v9 = f64const 0x2.0 + v10 = f64const 0x3.0 + v11 = f64const 0x4.0 + v12 = f64const 0x5.0 + v13 = f64const 0x6.0 + v14 = f64const 0x7.0 + v15 = f64const 0x8.0 + v16 = f64const 0x9.0 + v17 = f64const 0xa.0 + v18 = f64const 0xb.0 + v19 = call fn0(v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) + v20 = iadd v0, v1 + v21 = iadd v20, v2 + v22 = iadd v21, v3 + v23 = iadd v22, v4 + v24 = iadd v23, v5 + v25 = iadd v24, v6 + v26 = iadd v25, v7 + v27 = iadd v26, v19 + return v27 +} + +; VCode: +; addi sp,sp,-16 +; sd ra,8(sp) +; sd fp,0(sp) +; mv fp,sp +; addi sp,sp,-64 +; sd s1,56(sp) +; sd s2,48(sp) +; sd s3,40(sp) +; sd s4,32(sp) +; sd s5,24(sp) +; sd s6,16(sp) +; sd s7,8(sp) +; sd s8,0(sp) +; lui t6,-1 +; addi t6,t6,-32 +; add sp,sp,t6 +; block0: +; mv s1,a7 +; mv s2,a6 +; mv s3,a5 +; mv s4,a4 +; mv s5,a3 +; mv s6,a2 +; mv s7,a1 +; mv s8,a0 +; lui a0,1023 +; slli a0,a0,40 +; fmv.d.x fa0,a0 +; lui a0,1 +; slli a0,a0,50 +; fmv.d.x fa1,a0 +; lui a0,2049 +; slli a0,a0,39 +; fmv.d.x fa2,a0 +; lui a0,1025 +; slli a0,a0,40 +; fmv.d.x fa3,a0 +; lui a0,4101 +; slli a0,a0,38 +; fmv.d.x fa4,a0 +; lui a0,2051 +; slli a0,a0,39 +; fmv.d.x fa5,a0 +; lui a0,4103 +; slli a0,a0,38 +; fmv.d.x fa6,a0 +; lui a0,513 +; slli a0,a0,41 +; fmv.d.x fa7,a0 +; lui a0,8209 +; slli a0,a0,37 +; fmv.d.x ft0,a0 +; lui a0,4105 +; slli a0,a0,38 +; fmv.d.x ft1,a0 +; lui a0,8211 +; slli a0,a0,37 +; fmv.d.x ft2,a0 +; fsd ft0,0(sp) +; fsd ft1,8(sp) +; fsd ft2,16(sp) +; call %use_all +; mv a1,s8 +; mv a2,s7 +; add a1,a1,a2 +; mv a2,s6 +; add a1,a1,a2 +; mv a3,s5 +; add a1,a1,a3 +; mv a4,s4 +; add a1,a1,a4 +; mv a5,s3 +; add a1,a1,a5 +; mv a6,s2 +; add a1,a1,a6 +; mv a7,s1 +; add a1,a1,a7 +; add a0,a1,a0 +; lui t6,1 +; addi t6,t6,32 +; add sp,sp,t6 +; ld s1,56(sp) +; ld s2,48(sp) +; ld s3,40(sp) +; ld s4,32(sp) +; ld s5,24(sp) +; ld s6,16(sp) +; ld s7,8(sp) +; ld s8,0(sp) +; addi sp,sp,64 +; ld ra,8(sp) +; ld fp,0(sp) +; addi sp,sp,16 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; c.addi16sp sp, -0x10 +; c.sdsp ra, 8(sp) +; c.sdsp s0, 0(sp) +; c.mv s0, sp +; c.addi16sp sp, -0x40 +; c.sdsp s1, 0x38(sp) +; c.sdsp s2, 0x30(sp) +; c.sdsp s3, 0x28(sp) +; c.sdsp s4, 0x20(sp) +; c.sdsp s5, 0x18(sp) +; c.sdsp s6, 0x10(sp) +; c.sdsp s7, 8(sp) +; c.sdsp s8, 0(sp) +; c.lui t6, 0xfffff +; c.addi t6, -0x20 +; c.add sp, t6 +; block1: ; offset 0x20 +; c.mv s1, a7 +; c.mv s2, a6 +; c.mv s3, a5 +; c.mv s4, a4 +; c.mv s5, a3 +; c.mv s6, a2 +; c.mv s7, a1 +; c.mv s8, a0 +; lui a0, 0x3ff +; c.slli a0, 0x28 +; fmv.d.x fa0, a0 +; c.lui a0, 1 +; c.slli a0, 0x32 +; fmv.d.x fa1, a0 +; lui a0, 0x801 +; c.slli a0, 0x27 +; fmv.d.x fa2, a0 +; lui a0, 0x401 +; c.slli a0, 0x28 +; fmv.d.x fa3, a0 +; lui a0, 0x1005 +; c.slli a0, 0x26 +; fmv.d.x fa4, a0 +; lui a0, 0x803 +; c.slli a0, 0x27 +; fmv.d.x fa5, a0 +; lui a0, 0x1007 +; c.slli a0, 0x26 +; fmv.d.x fa6, a0 +; lui a0, 0x201 +; c.slli a0, 0x29 +; fmv.d.x fa7, a0 +; lui a0, 0x2011 +; c.slli a0, 0x25 +; fmv.d.x ft0, a0 +; lui a0, 0x1009 +; c.slli a0, 0x26 +; fmv.d.x ft1, a0 +; lui a0, 0x2013 +; c.slli a0, 0x25 +; fmv.d.x ft2, a0 +; c.fsdsp ft0, 0(sp) +; c.fsdsp ft1, 8(sp) +; c.fsdsp ft2, 0x10(sp) +; auipc ra, 0 ; reloc_external RiscvCallPlt %use_all 0 +; jalr ra +; c.mv a1, s8 +; c.mv a2, s7 +; c.add a1, a2 +; c.mv a2, s6 +; c.add a1, a2 +; c.mv a3, s5 +; c.add a1, a3 +; c.mv a4, s4 +; c.add a1, a4 +; c.mv a5, s3 +; c.add a1, a5 +; c.mv a6, s2 +; c.add a1, a6 +; c.mv a7, s1 +; c.add a1, a7 +; c.add a0, a1 +; c.lui t6, 1 +; addi t6, t6, 0x20 +; c.add sp, t6 +; c.ldsp s1, 0x38(sp) +; c.ldsp s2, 0x30(sp) +; c.ldsp s3, 0x28(sp) +; c.ldsp s4, 0x20(sp) +; c.ldsp s5, 0x18(sp) +; c.ldsp s6, 0x10(sp) +; c.ldsp s7, 8(sp) +; c.ldsp s8, 0(sp) +; c.addi16sp sp, 0x40 +; c.ldsp ra, 8(sp) +; c.ldsp s0, 0(sp) +; c.addi16sp sp, 0x10 +; c.jr ra +