Repository: bytecodealliance/wasmtime
Pull request #8389 (2024-04-16 22:29:21)

Use callee-save registers in tail calls on aarch64
Switch back to mostly following the AArch64 ABI for callee-save registers with the tail calling convention, except that we still reserve x0 for the return area pointer and x1 for the destination of an indirect tail call.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs
index 5327ee049..1c3ffc37b 100644
--- a/cranelift/codegen/src/isa/aarch64/abi.rs
+++ b/cranelift/codegen/src/isa/aarch64/abi.rs
@@ -14,7 +14,7 @@ use crate::settings;
 use crate::{CodegenError, CodegenResult};
 use alloc::boxed::Box;
 use alloc::vec::Vec;
-use regalloc2::{MachineEnv, PReg, PRegSet, VReg};
+use regalloc2::{MachineEnv, PReg, PRegSet};
 use smallvec::{smallvec, SmallVec};
 use std::sync::OnceLock;
 
@@ -109,10 +109,6 @@ impl ABIMachineSpec for AArch64MachineDeps {
         add_ret_area_ptr: bool,
         mut args: ArgsAccumulator,
     ) -> CodegenResult<(u32, Option<usize>)> {
-        if matches!(call_conv, isa::CallConv::Tail) {
-            return compute_arg_locs_tail(params, add_ret_area_ptr, args);
-        }
-
         let is_apple_cc = call_conv.extends_apple_aarch64();
 
         // See AArch64 ABI (https://github.com/ARM-software/abi-aa/blob/2021Q1/aapcs64/aapcs64.rst#64parameter-passing), sections 6.4.
@@ -129,7 +125,20 @@ impl ABIMachineSpec for AArch64MachineDeps {
         // break our other invariants that the stack is always allocated in
         // 16-bytes chunks.
 
-        let mut next_xreg = 0;
+        let mut next_xreg = if call_conv == isa::CallConv::Tail {
+            // We reserve `x0` for the return area pointer. For simplicity, we
+            // reserve it even when there is no return area pointer needed. This
+            // also means that identity functions don't have to shuffle arguments to
+            // different return registers because we shifted all argument register
+            // numbers down by one to make space for the return area pointer.
+            //
+            // Also, we cannot use all allocatable GPRs as arguments because we need
+            // at least one allocatable register for holding the callee address in
+            // indirect calls. So skip `x1` also, reserving it for that role.
+            2
+        } else {
+            0
+        };
         let mut next_vreg = 0;
         let mut next_stack: u32 = 0;
 
@@ -155,6 +164,20 @@ impl ABIMachineSpec for AArch64MachineDeps {
 
             let (rcs, reg_types) = Inst::rc_for_type(param.value_type)?;
 
+            if matches!(
+                param.purpose,
+                ir::ArgumentPurpose::StructArgument(_)
+                    | ir::ArgumentPurpose::StructReturn
+                    | ir::ArgumentPurpose::StackLimit
+            ) {
+                assert!(
+                    call_conv != isa::CallConv::Tail,
+                    "support for {:?} parameters is not implemented for the `tail` calling \
+                    convention yet",
+                    param.purpose,
+                );
+            }
+
             if let ir::ArgumentPurpose::StructArgument(size) = param.purpose {
                 assert_eq!(args_or_rets, ArgsOrRets::Args);
                 let offset = next_stack as i64;
@@ -335,21 +358,30 @@ impl ABIMachineSpec for AArch64MachineDeps {
 
         let extra_arg = if add_ret_area_ptr {
             debug_assert!(args_or_rets == ArgsOrRets::Args);
-            if next_xreg < max_per_class_reg_vals && remaining_reg_vals > 0 {
+            if call_conv == isa::CallConv::Tail {
                 args.push_non_formal(ABIArg::reg(
-                    xreg(next_xreg).to_real_reg().unwrap(),
+                    xreg_preg(0).into(),
                     I64,
                     ir::ArgumentExtension::None,
                     ir::ArgumentPurpose::Normal,
                 ));
             } else {
-                args.push_non_formal(ABIArg::stack(
-                    next_stack as i64,
-                    I64,
-                    ir::ArgumentExtension::None,
-                    ir::ArgumentPurpose::Normal,
-                ));
-                next_stack += 8;
+                if next_xreg < max_per_class_reg_vals && remaining_reg_vals > 0 {
+                    args.push_non_formal(ABIArg::reg(
+                        xreg(next_xreg).to_real_reg().unwrap(),
+                        I64,
+                        ir::ArgumentExtension::None,
+                        ir::ArgumentPurpose::Normal,
+                    ));
+                } else {
+                    args.push_non_formal(ABIArg::stack(
+                        next_stack as i64,
+                        I64,
+                        ir::ArgumentExtension::None,
+                        ir::ArgumentPurpose::Normal,
+                    ));
+                    next_stack += 8;
+                }
             }
             Some(args.args().len() - 1)
         } else {
@@ -690,16 +722,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
         flags: &settings::Flags,
         frame_layout: &FrameLayout,
     ) -> SmallVec<[Inst; 16]> {
-        let mut clobbered_int = vec![];
-        let mut clobbered_vec = vec![];
-
-        for &reg in frame_layout.clobbered_callee_saves.iter() {
-            match reg.to_reg().class() {
-                RegClass::Int => clobbered_int.push(reg),
-                RegClass::Float => clobbered_vec.push(reg),
-                RegClass::Vector => unreachable!(),
-            }
-        }
+        let (clobbered_int, clobbered_vec) = frame_layout.clobbered_callee_saves_by_class();
 
         let mut insts = SmallVec::new();
         let setup_frame = frame_layout.setup_area_size > 0;
@@ -923,16 +946,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
         frame_layout: &FrameLayout,
     ) -> SmallVec<[Inst; 16]> {
         let mut insts = SmallVec::new();
-        let mut clobbered_int = vec![];
-        let mut clobbered_vec = vec![];
-
-        for &reg in frame_layout.clobbered_callee_saves.iter() {
-            match reg.to_reg().class() {
-                RegClass::Int => clobbered_int.push(reg),
-                RegClass::Float => clobbered_vec.push(reg),
-                RegClass::Vector => unreachable!(),
-            }
-        }
+        let (clobbered_int, clobbered_vec) = frame_layout.clobbered_callee_saves_by_class();
 
         // Free the fixed frame if necessary.
         let stack_size = frame_layout.fixed_frame_storage_size + frame_layout.outgoing_args_size;
@@ -1150,11 +1164,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
         }
     }
 
-    fn get_regs_clobbered_by_call(call_conv_of_callee: isa::CallConv) -> PRegSet {
-        match call_conv_of_callee {
-            isa::CallConv::Tail => ALL_CLOBBERS,
-            _ => DEFAULT_AAPCS_CLOBBERS,
-        }
+    fn get_regs_clobbered_by_call(_call_conv: isa::CallConv) -> PRegSet {
+        DEFAULT_AAPCS_CLOBBERS
     }
 
     fn get_ext_mode(
@@ -1189,7 +1200,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
 
         // Sort registers for deterministic code output. We can do an unstable
         // sort because the registers will be unique (there are no dups).
-        regs.sort_unstable_by_key(|r| VReg::from(r.to_reg()).vreg());
+        regs.sort_unstable();
 
         // Compute clobber size.
         let clobber_size = compute_clobber_size(&regs);
@@ -1343,124 +1354,6 @@ impl AArch64CallSite {
     }
 }
 
-fn compute_arg_locs_tail(
-    params: &[ir::AbiParam],
-    add_ret_area_ptr: bool,
-    mut args: ArgsAccumulator,
-) -> CodegenResult<(u32, Option<usize>)> {
-    let mut xregs = ALL_CLOBBERS
-        .into_iter()
-        .filter(|r| r.class() == RegClass::Int)
-        // We reserve `x0` for the return area pointer. For simplicity, we
-        // reserve it even when there is no return area pointer needed. This
-        // also means that identity functions don't have to shuffle arguments to
-        // different return registers because we shifted all argument register
-        // numbers down by one to make space for the return area pointer.
-        //
-        // Also, we cannot use all allocatable GPRs as arguments because we need
-        // at least one allocatable register for holding the callee address in
-        // indirect calls. So skip `x1` also, reserving it for that role.
-        .skip(2);
-
-    let mut vregs = ALL_CLOBBERS
-        .into_iter()
-        .filter(|r| r.class() == RegClass::Float);
-
-    let mut next_stack: u32 = 0;
-
-    // Get the next stack slot for the given type.
-    let stack = |next_stack: &mut u32, ty: ir::Type| {
-        *next_stack = align_to(*next_stack, ty.bytes());
-        let offset = i64::from(*next_stack);
-        *next_stack += ty.bytes();
-        ABIArgSlot::Stack {
-            offset,
-            ty,
-            extension: ir::ArgumentExtension::None,
-        }
-    };
-
-    // Get the next `x` register available, or a stack slot if all are in use.
-    let mut xreg = |next_stack: &mut u32, ty| {
-        xregs
-            .next()
-            .map(|reg| ABIArgSlot::Reg {
-                reg: reg.into(),
-                ty,
-                extension: ir::ArgumentExtension::None,
-            })
-            .unwrap_or_else(|| stack(next_stack, ty))
-    };
-
-    // Get the next `v` register available, or a stack slot if all are in use.
-    let mut vreg = |next_stack: &mut u32, ty| {
-        vregs
-            .next()
-            .map(|reg| ABIArgSlot::Reg {
-                reg: reg.into(),
-                ty,
-                extension: ir::ArgumentExtension::None,
-            })
-            .unwrap_or_else(|| stack(next_stack, ty))
-    };
-
-    for param in params {
-        assert!(
-            legal_type_for_machine(param.value_type),
-            "Invalid type for AArch64: {:?}",
-            param.value_type
-        );
-
-        match param.purpose {
-            ir::ArgumentPurpose::Normal | ir::ArgumentPurpose::VMContext => {}
-            ir::ArgumentPurpose::StructArgument(_)
-            | ir::ArgumentPurpose::StructReturn
-            | ir::ArgumentPurpose::StackLimit => unimplemented!(
-                "support for {:?} parameters is not implemented for the `tail` \
-                 calling convention yet",
-                param.purpose,
-            ),
-        }
-
-        let (reg_classes, reg_types) = Inst::rc_for_type(param.value_type)?;
-        args.push(ABIArg::Slots {
-            slots: reg_classes
-                .iter()
-                .zip(reg_types)
-                .map(|(cls, ty)| match cls {
-                    RegClass::Int => xreg(&mut next_stack, *ty),
-                    RegClass::Float => vreg(&mut next_stack, *ty),
-                    RegClass::Vector => unreachable!(),
-                })
-                .collect(),
-            purpose: param.purpose,
-        });
-    }
-
-    let ret_ptr = if add_ret_area_ptr {
-        let idx = args.args().len();
-        args.push(ABIArg::reg(
-            xreg_preg(0).into(),
-            types::I64,
-            ir::ArgumentExtension::None,
-            ir::ArgumentPurpose::Normal,
-        ));
-        Some(idx)
-    } else {
-        None
-    };
-
-    next_stack = align_to(next_stack, 16);
-
-    // To avoid overflow issues, limit the arg/return size to something
-    // reasonable -- here, 128 MB.
-    if next_stack > STACK_ARG_RET_SIZE_LIMIT {
-        return Err(CodegenError::ImplLimitExceeded);
-    }
-
-    Ok((next_stack, ret_ptr))
-}
-
 /// Is this type supposed to be seen on this machine? E.g. references of the
 /// wrong width are invalid.
 fn legal_type_for_machine(ty: Type) -> bool {
@@ -1473,15 +1366,11 @@ fn legal_type_for_machine(ty: Type) -> bool {
 /// Is the given register saved in the prologue if clobbered, i.e., is it a
 /// callee-save?
 fn is_reg_saved_in_prologue(
-    call_conv: isa::CallConv,
+    _call_conv: isa::CallConv,
     enable_pinned_reg: bool,
     sig: &Signature,
     r: RealReg,
 ) -> bool {
-    if call_conv == isa::CallConv::Tail {
-        return false;
-    }
-
     // FIXME: We need to inspect whether a function is returning Z or P regs too.
     let save_z_regs = sig
         .params
@@ -1591,72 +1480,6 @@ const fn default_aapcs_clobbers() -> PRegSet {
 
 const DEFAULT_AAPCS_CLOBBERS: PRegSet = default_aapcs_clobbers();
 
-// For calling conventions that clobber all registers.
-const ALL_CLOBBERS: PRegSet = PRegSet::empty()
-    .with(xreg_preg(0))
-    .with(xreg_preg(1))
-    .with(xreg_preg(2))
-    .with(xreg_preg(3))
-    .with(xreg_preg(4))
-    .with(xreg_preg(5))
-    .with(xreg_preg(6))
-    .with(xreg_preg(7))
-    .with(xreg_preg(8))
-    .with(xreg_preg(9))
-    .with(xreg_preg(10))
-    .with(xreg_preg(11))
-    .with(xreg_preg(12))
-    .with(xreg_preg(13))
-    .with(xreg_preg(14))
-    .with(xreg_preg(15))
-    // Cranelift reserves x16 and x17 as unallocatable scratch registers.
-    //
-    // x18 can be used by the platform and therefore is not allocatable.
-    .with(xreg_preg(19))
-    .with(xreg_preg(20))
-    .with(xreg_preg(21))
-    .with(xreg_preg(22))
-    .with(xreg_preg(23))
-    .with(xreg_preg(24))
-    .with(xreg_preg(25))
-    .with(xreg_preg(26))
-    .with(xreg_preg(27))
-    .with(xreg_preg(28))
-    // NB: x29 is the FP, x30 is the link register, and x31 is the SP. None of
-    // these are allocatable.
-    .with(vreg_preg(0))
-    .with(vreg_preg(1))
-    .with(vreg_preg(2))
-    .with(vreg_preg(3))
-    .with(vreg_preg(4))
-    .with(vreg_preg(5))
-    .with(vreg_preg(6))
-    .with(vreg_preg(7))
-    .with(vreg_preg(8))
-    .with(vreg_preg(9))
-    .with(vreg_preg(10))
-    .with(vreg_preg(11))
-    .with(vreg_preg(12))
-    .with(vreg_preg(13))
-    .with(vreg_preg(14))
-    .with(vreg_preg(15))
-    .with(vreg_preg(16))
-    .with(vreg_preg(17))
-    .with(vreg_preg(18))
-    .with(vreg_preg(19))
-    .with(vreg_preg(20))
-    .with(vreg_preg(21))
-    .with(vreg_preg(22))
-    .with(vreg_preg(23))
-    .with(vreg_preg(24))
-    .with(vreg_preg(25))
-    .with(vreg_preg(26))
-    .with(vreg_preg(27))
-    .with(vreg_preg(28))
-    .with(vreg_preg(29))
-    .with(vreg_preg(30))
-    .with(vreg_preg(31));
-
 fn create_reg_env(enable_pinned_reg: bool) -> MachineEnv {
     fn preg(r: Reg) -> PReg {
         r.to_real_reg().unwrap().into()
diff --git a/cranelift/codegen/src/isa/riscv64/abi.rs b/cranelift/codegen/src/isa/riscv64/abi.rs
index 9bf3a9b84..ee9869904 100644
--- a/cranelift/codegen/src/isa/riscv64/abi.rs
+++ b/cranelift/codegen/src/isa/riscv64/abi.rs
@@ -694,7 +694,7 @@ impl ABIMachineSpec for Riscv64MachineDeps {
             .filter(|r| is_reg_saved_in_prologue(call_conv, r.to_reg()))
             .collect();
 
-        regs.sort();
+        regs.sort_unstable();
 
         // Compute clobber size.
         let clobber_size = compute_clobber_size(&regs);
diff --git a/cranelift/codegen/src/isa/s390x/abi.rs b/cranelift/codegen/src/isa/s390x/abi.rs
index bbed8485c..321ec1e5d 100644
--- a/cranelift/codegen/src/isa/s390x/abi.rs
+++ b/cranelift/codegen/src/isa/s390x/abi.rs
@@ -79,7 +79,7 @@ use crate::machinst::*;
 use crate::settings;
 use crate::{CodegenError, CodegenResult};
 use alloc::vec::Vec;
-use regalloc2::{MachineEnv, PReg, PRegSet};
+use regalloc2::{MachineEnv, PRegSet};
 use smallvec::{smallvec, SmallVec};
 use std::sync::OnceLock;
 
@@ -599,8 +599,7 @@ impl ABIMachineSpec for S390xMachineDeps {
         let mut insts = SmallVec::new();
 
         // Collect clobbered registers.
-        let (first_clobbered_gpr, clobbered_fpr) =
-            get_clobbered_gpr_fpr(&frame_layout.clobbered_callee_saves);
+        let (first_clobbered_gpr, clobbered_fpr) = get_clobbered_gpr_fpr(frame_layout);
         if flags.unwind_info() {
             insts.push(Inst::Unwind {
                 inst: UnwindInst::DefineNewFrame {
@@ -696,8 +695,7 @@ impl ABIMachineSpec for S390xMachineDeps {
         let mut insts = SmallVec::new();
 
         // Collect clobbered registers.
-        let (first_clobbered_gpr, clobbered_fpr) =
-            get_clobbered_gpr_fpr(&frame_layout.clobbered_callee_saves);
+        let (first_clobbered_gpr, clobbered_fpr) = get_clobbered_gpr_fpr(frame_layout);
 
         // Restore FPRs.
         for (i, reg) in clobbered_fpr.iter().enumerate() {
@@ -851,7 +849,7 @@ impl ABIMachineSpec for S390xMachineDeps {
 
         // Sort registers for deterministic code output. We can do an unstable
         // sort because the registers will be unique (there are no dups).
-        regs.sort_unstable_by_key(|r| PReg::from(r.to_reg()).index());
+        regs.sort_unstable();
 
         // Compute clobber size.  We only need to count FPR save slots.
         let mut clobber_size = 0;
@@ -892,28 +890,18 @@ fn is_reg_saved_in_prologue(_call_conv: isa::CallConv, r: RealReg) -> bool {
     }
 }
 
-fn get_clobbered_gpr_fpr(
-    clobbered_callee_saves: &[Writable<RealReg>],
-) -> (u8, SmallVec<[Writable<RealReg>; 8]>) {
+fn get_clobbered_gpr_fpr(frame_layout: &FrameLayout) -> (u8, &[Writable<RealReg>]) {
     // Collect clobbered registers.  Note we save/restore GPR always as
     // a block of registers using LOAD MULTIPLE / STORE MULTIPLE, starting
     // with the clobbered GPR with the lowest number up to %r15.  We
     // return the number of that first GPR (or 16 if none is to be saved).
-    let mut clobbered_fpr = SmallVec::new();
-    let mut first_clobbered_gpr = 16;
-
-    for &reg in clobbered_callee_saves.iter() {
-        match reg.to_reg().class() {
-            RegClass::Int => {
-                let enc = reg.to_reg().hw_enc();
-                if enc < first_clobbered_gpr {
-                    first_clobbered_gpr = enc;
-                }
-            }
-            RegClass::Float => clobbered_fpr.push(reg),
-            RegClass::Vector => unreachable!(),
-        }
-    }
+    let (clobbered_gpr, clobbered_fpr) = frame_layout.clobbered_callee_saves_by_class();
+
+    let first_clobbered_gpr = clobbered_gpr.split_first().map_or(16, |(first, rest)| {
+        let first = first.to_reg().hw_enc();
+        debug_assert!(rest.iter().all(|r| r.to_reg().hw_enc() > first));
+        first
+    });
 
     (first_clobbered_gpr, clobbered_fpr)
 }
diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs
index c1e15680a..4f13df1de 100644
--- a/cranelift/codegen/src/isa/x64/abi.rs
+++ b/cranelift/codegen/src/isa/x64/abi.rs
@@ -11,7 +11,7 @@ use crate::{CodegenError, CodegenResult};
 use alloc::boxed::Box;
 use alloc::vec::Vec;
 use args::*;
-use regalloc2::{MachineEnv, PReg, PRegSet, VReg};
+use regalloc2::{MachineEnv, PReg, PRegSet};
 use smallvec::{smallvec, SmallVec};
 use std::sync::OnceLock;
 
@@ -999,7 +999,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
         };
         // Sort registers for deterministic code output. We can do an unstable sort because the
         // registers will be unique (there are no dups).
-        regs.sort_unstable_by_key(|r| VReg::from(r.to_reg()).vreg());
+        regs.sort_unstable();
 
         // Compute clobber size.
         let clobber_size = compute_clobber_size(&regs);
diff --git a/cranelift/codegen/src/isa/x64/pcc.rs b/cranelift/codegen/src/isa/x64/pcc.rs
index acf8e54c2..bdae2d57a 100644
--- a/cranelift/codegen/src/isa/x64/pcc.rs
+++ b/cranelift/codegen/src/isa/x64/pcc.rs
@@ -374,7 +374,12 @@ pub(crate) fn check(
             let addr = addr.clone();
             let bits: u16 = size.to_bits().into();
             check_output(ctx, vcode, dst.to_writable_reg(), &[], |vcode| {
-                clamp_range(ctx, 64, bits, compute_addr(ctx, vcode, &addr, bits))
+                let fact = if let SyntheticAmode::Real(amode) = &addr {
+                    compute_addr(ctx, vcode, amode, bits)
+                } else {
+                    None
+                };
+                clamp_range(ctx, 64, bits, fact)
             })
         }
 
@@ -922,15 +927,12 @@ fn check_mem<'a>(
     ty: Type,
     op: LoadOrStore<'a>,
 ) -> PccResult<Option<Fact>> {
-    match amode {
-        SyntheticAmode::Real(amode) if !amode.get_flags().checked() => return Ok(None),
-        SyntheticAmode::IncomingArg { .. }
-        | SyntheticAmode::NominalSPOffset { .. }
-        | SyntheticAmode::ConstantOffset(_) => return Ok(None),
-        _ => {}
-    }
-
-    let addr = compute_addr(ctx, vcode, amode, 64).ok_or(PccError::MissingFact)?;
+    let addr = match amode {
+        SyntheticAmode::Real(amode) if amode.get_flags().checked() => {
+            compute_addr(ctx, vcode, amode, 64).ok_or(PccError::MissingFact)?
+        }
+        _ => return Ok(None),
+    };
 
     match op {
         LoadOrStore::Load {
@@ -957,15 +959,10 @@ fn check_mem<'a>(
     }
 }
 
-fn compute_addr(
-    ctx: &FactContext,
-    vcode: &VCode<Inst>,
-    amode: &SyntheticAmode,
-    bits: u16,
-) -> Option<Fact> {
+fn compute_addr(ctx: &FactContext, vcode: &VCode<Inst>, amode: &Amode, bits: u16) -> Option<Fact> {
     trace!("compute_addr: {:?}", amode);
     match *amode {
-        SyntheticAmode::Real(Amode::ImmReg { simm32, base, .. }) => {
+        Amode::ImmReg { simm32, base, .. } => {
             let base = get_fact_or_default(vcode, base, bits);
             trace!("base = {:?}", base);
             let simm32: i64 = simm32.into();
@@ -975,13 +972,13 @@ fn compute_addr(
             trace!("sum = {:?}", sum);
             Some(sum)
         }
-        SyntheticAmode::Real(Amode::ImmRegRegShift {
+        Amode::ImmRegRegShift {
             simm32,
             base,
             index,
             shift,
             ..
-        }) => {
+        } => {
             let base = get_fact_or_default(vcode, base.into(), bits);
             let index = get_fact_or_default(vcode, index.into(), bits);
             trace!("base = {:?} index = {:?}", base, index);
@@ -994,9 +991,6 @@ fn compute_addr(
             trace!("sum = {:?}", sum);
             Some(sum)
         }
-        SyntheticAmode::Real(Amode::RipRelative { .. })
-        | SyntheticAmode::IncomingArg { .. }
-        | SyntheticAmode::ConstantOffset(_)
-        | SyntheticAmode::NominalSPOffset { .. } => None,
+        Amode::RipRelative { .. } => None,
     }
 }
diff --git a/cranelift/codegen/src/machinst/abi.rs b/cranelift/codegen/src/machinst/abi.rs
index 0e58660bb..b4edf0323 100644
--- a/cranelift/codegen/src/machinst/abi.rs
+++ b/cranelift/codegen/src/machinst/abi.rs
@@ -1055,6 +1055,22 @@ pub struct FrameLayout {
     pub clobbered_callee_saves: Vec<Writable<RealReg>>,
 }
 
+impl FrameLayout {
+    /// Split the clobbered callee-save registers into integer-class and
+    /// float-class groups.
+    ///
+    /// This method does not currently support vector-class callee-save
+    /// registers because no current backend has them.
+    pub fn clobbered_callee_saves_by_class(&self) -> (&[Writable<RealReg>], &[Writable<RealReg>]) {
+        let (ints, floats) = self.clobbered_callee_saves.split_at(
+            self.clobbered_callee_saves
+                .partition_point(|r| r.to_reg().class() == RegClass::Int),
+        );
+        debug_assert!(floats.iter().all(|r| r.to_reg().class() == RegClass::Float));
+        (ints, floats)
+    }
+}
+
 /// ABI object for a function body.
 pub struct Callee<M: ABIMachineSpec> {
     /// CLIF-level signature, possibly normalized.
diff --git a/cranelift/docs/ir.md b/cranelift/docs/ir.md
index 9ba944c63..832cae39d 100644
--- a/cranelift/docs/ir.md
+++ b/cranelift/docs/ir.md
@@ -556,7 +556,7 @@ GV = [colocated] symbol Name
 
 A few instructions have variants that take immediate operands, but in general
 an instruction is required to load a constant into an SSA value: `iconst`,
-`f32const`, `f64const` and `bconst` serve this purpose.
+`f32const` and `f64const` serve this purpose.
 
 ### Bitwise operations
 
diff --git a/crates/wasi-http/src/types.rs b/crates/wasi-http/src/types.rs
index 467304355..28ab76863 100644
--- a/crates/wasi-http/src/types.rs
+++ b/crates/wasi-http/src/types.rs
@@ -140,11 +140,17 @@ pub fn default_send_request(
     request: hyper::Request<HyperOutgoingBody>,
     config: OutgoingRequestConfig,
 ) -> HostFutureIncomingResponse {
-    let handle = wasmtime_wasi::runtime::spawn(async move { Ok(handler(request, config).await) });
+    let handle = wasmtime_wasi::runtime::spawn(async move {
+        Ok(default_send_request_handler(request, config).await)
+    });
     HostFutureIncomingResponse::pending(handle)
 }
 
-async fn handler(
+/// The underlying implementation of how an outgoing request is sent. This should likely be spawned
+/// in a task.
+///
+/// This is called from [default_send_request] to actually send the request.
+pub async fn default_send_request_handler(
     mut request: hyper::Request<HyperOutgoingBody>,
     OutgoingRequestConfig {
         use_tls,


Test patch:
diff --git a/cranelift/filetests/filetests/isa/aarch64/fuzzbug-60035.clif b/cranelift/filetests/filetests/isa/aarch64/fuzzbug-60035.clif
index ebddc1125..fa453d757 100644
--- a/cranelift/filetests/filetests/isa/aarch64/fuzzbug-60035.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/fuzzbug-60035.clif
@@ -15,33 +15,15 @@ block0:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
-;   stp x27, x28, [sp, #-16]!
-;   stp x25, x26, [sp, #-16]!
-;   stp x23, x24, [sp, #-16]!
-;   stp x21, x22, [sp, #-16]!
-;   stp x19, x20, [sp, #-16]!
-;   stp d14, d15, [sp, #-16]!
-;   stp d12, d13, [sp, #-16]!
-;   stp d10, d11, [sp, #-16]!
-;   stp d8, d9, [sp, #-16]!
-;   sub sp, sp, #16
+;   str x20, [sp, #-16]!
 ; block0:
 ;   load_ext_name x1, User(userextname0)+0
-;   str x1, [sp]
-;   ldr x1, [sp]
+;   mov x20, x1
+;   mov x1, x20
 ;   blr x1
-;   ldr x1, [sp]
+;   mov x1, x20
 ;   blr x1
-;   add sp, sp, #16
-;   ldp d8, d9, [sp], #16
-;   ldp d10, d11, [sp], #16
-;   ldp d12, d13, [sp], #16
-;   ldp d14, d15, [sp], #16
-;   ldp x19, x20, [sp], #16
-;   ldp x21, x22, [sp], #16
-;   ldp x23, x24, [sp], #16
-;   ldp x25, x26, [sp], #16
-;   ldp x27, x28, [sp], #16
+;   ldr x20, [sp], #16
 ;   ldp fp, lr, [sp], #16
 ;   ret
 ;
@@ -49,36 +31,18 @@ block0:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
-;   stp x27, x28, [sp, #-0x10]!
-;   stp x25, x26, [sp, #-0x10]!
-;   stp x23, x24, [sp, #-0x10]!
-;   stp x21, x22, [sp, #-0x10]!
-;   stp x19, x20, [sp, #-0x10]!
-;   stp d14, d15, [sp, #-0x10]!
-;   stp d12, d13, [sp, #-0x10]!
-;   stp d10, d11, [sp, #-0x10]!
-;   stp d8, d9, [sp, #-0x10]!
-;   sub sp, sp, #0x10
-; block1: ; offset 0x30
-;   ldr x1, #0x38
-;   b #0x40
+;   str x20, [sp, #-0x10]!
+; block1: ; offset 0xc
+;   ldr x1, #0x14
+;   b #0x1c
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 u1:7 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   stur x1, [sp]
-;   ldur x1, [sp]
+;   mov x20, x1
+;   mov x1, x20
 ;   blr x1
-;   ldur x1, [sp]
+;   mov x1, x20
 ;   blr x1
-;   add sp, sp, #0x10
-;   ldp d8, d9, [sp], #0x10
-;   ldp d10, d11, [sp], #0x10
-;   ldp d12, d13, [sp], #0x10
-;   ldp d14, d15, [sp], #0x10
-;   ldp x19, x20, [sp], #0x10
-;   ldp x21, x22, [sp], #0x10
-;   ldp x23, x24, [sp], #0x10
-;   ldp x25, x26, [sp], #0x10
-;   ldp x27, x28, [sp], #0x10
+;   ldr x20, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
 ;   ret
 
diff --git a/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif b/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif
index 1e587efb4..96b682174 100644
--- a/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif
@@ -217,92 +217,143 @@ block0:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
-;   sub sp, sp, #16
-;   ldr fp, [sp, #16]
+;   sub sp, sp, #160
+;   ldr fp, [sp, #160]
 ;   stp fp, lr, [sp]
 ;   mov fp, sp
+;   stp x27, x28, [sp, #-16]!
+;   stp x25, x26, [sp, #-16]!
+;   stp x23, x24, [sp, #-16]!
+;   stp x21, x22, [sp, #-16]!
+;   stp x19, x20, [sp, #-16]!
 ;   sub sp, sp, #16
 ; block0:
 ;   movz x2, #10
+;   str x2, [sp]
 ;   movz x3, #15
 ;   movz x4, #20
 ;   movz x5, #25
 ;   movz x6, #30
 ;   movz x7, #35
-;   movz x8, #40
-;   movz x9, #45
-;   movz x10, #50
-;   str x10, [sp]
-;   movz x11, #55
-;   movz x12, #60
-;   movz x13, #65
-;   movz x14, #70
-;   movz x15, #75
-;   movz x19, #80
-;   movz x20, #85
-;   movz x21, #90
-;   movz x22, #95
-;   movz x23, #100
-;   movz x24, #105
-;   movz x25, #110
-;   movz x26, #115
-;   movz x27, #120
-;   movz x28, #125
-;   movz x0, #130
-;   movz x1, #135
-;   load_ext_name x10, TestCase(%tail_callee_stack_args)+0
-;   str x0, [sp, #32]
-;   str x1, [sp, #40]
-;   mov x0, x10
-;   ldr x10, [sp]
-;   return_call_ind x0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
+;   movz x10, #40
+;   movz x11, #45
+;   movz x12, #50
+;   movz x13, #55
+;   movz x14, #60
+;   movz x15, #65
+;   movz x0, #70
+;   movz x1, #75
+;   movz x8, #80
+;   movz x9, #85
+;   movz x26, #90
+;   movz x27, #95
+;   movz x28, #100
+;   movz x21, #105
+;   movz x19, #110
+;   movz x20, #115
+;   movz x22, #120
+;   movz x23, #125
+;   movz x24, #130
+;   movz x25, #135
+;   load_ext_name x2, TestCase(%tail_callee_stack_args)+0
+;   str x10, [sp, #112]
+;   str x11, [sp, #120]
+;   str x12, [sp, #128]
+;   str x13, [sp, #136]
+;   str x14, [sp, #144]
+;   str x15, [sp, #152]
+;   str x0, [sp, #160]
+;   str x1, [sp, #168]
+;   str x8, [sp, #176]
+;   str x9, [sp, #184]
+;   str x26, [sp, #192]
+;   str x27, [sp, #200]
+;   str x28, [sp, #208]
+;   str x21, [sp, #216]
+;   str x19, [sp, #224]
+;   str x20, [sp, #232]
+;   str x22, [sp, #240]
+;   str x23, [sp, #248]
+;   str x24, [sp, #256]
+;   str x25, [sp, #264]
+;   mov x10, x2
+;   ldr x2, [sp]
+;   return_call_ind x10 new_stack_arg_size:160 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
-;   sub sp, sp, #0x10
-;   ldur x29, [sp, #0x10]
+;   sub sp, sp, #0xa0
+;   ldur x29, [sp, #0xa0]
 ;   stp x29, x30, [sp]
 ;   mov x29, sp
+;   stp x27, x28, [sp, #-0x10]!
+;   stp x25, x26, [sp, #-0x10]!
+;   stp x23, x24, [sp, #-0x10]!
+;   stp x21, x22, [sp, #-0x10]!
+;   stp x19, x20, [sp, #-0x10]!
 ;   sub sp, sp, #0x10
-; block1: ; offset 0x1c
+; block1: ; offset 0x30
 ;   mov x2, #0xa
+;   stur x2, [sp]
 ;   mov x3, #0xf
 ;   mov x4, #0x14
 ;   mov x5, #0x19
 ;   mov x6, #0x1e
 ;   mov x7, #0x23
-;   mov x8, #0x28
-;   mov x9, #0x2d
-;   mov x10, #0x32
-;   stur x10, [sp]
-;   mov x11, #0x37
-;   mov x12, #0x3c
-;   mov x13, #0x41
-;   mov x14, #0x46
-;   mov x15, #0x4b
-;   mov x19, #0x50
-;   mov x20, #0x55
-;   mov x21, #0x5a
-;   mov x22, #0x5f
-;   mov x23, #0x64
-;   mov x24, #0x69
-;   mov x25, #0x6e
-;   mov x26, #0x73
-;   mov x27, #0x78
-;   mov x28, #0x7d
-;   mov x0, #0x82
-;   mov x1, #0x87
-;   ldr x10, #0x90
-;   b #0x98
+;   mov x10, #0x28
+;   mov x11, #0x2d
+;   mov x12, #0x32
+;   mov x13, #0x37
+;   mov x14, #0x3c
+;   mov x15, #0x41
+;   mov x0, #0x46
+;   mov x1, #0x4b
+;   mov x8, #0x50
+;   mov x9, #0x55
+;   mov x26, #0x5a
+;   mov x27, #0x5f
+;   mov x28, #0x64
+;   mov x21, #0x69
+;   mov x19, #0x6e
+;   mov x20, #0x73
+;   mov x22, #0x78
+;   mov x23, #0x7d
+;   mov x24, #0x82
+;   mov x25, #0x87
+;   ldr x2, #0xa4
+;   b #0xac
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %tail_callee_stack_args 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   stur x0, [sp, #0x20]
-;   stur x1, [sp, #0x28]
-;   mov x0, x10
-;   ldur x10, [sp]
+;   stur x10, [sp, #0x70]
+;   stur x11, [sp, #0x78]
+;   stur x12, [sp, #0x80]
+;   stur x13, [sp, #0x88]
+;   stur x14, [sp, #0x90]
+;   stur x15, [sp, #0x98]
+;   stur x0, [sp, #0xa0]
+;   stur x1, [sp, #0xa8]
+;   stur x8, [sp, #0xb0]
+;   stur x9, [sp, #0xb8]
+;   stur x26, [sp, #0xc0]
+;   stur x27, [sp, #0xc8]
+;   stur x28, [sp, #0xd0]
+;   stur x21, [sp, #0xd8]
+;   stur x19, [sp, #0xe0]
+;   stur x20, [sp, #0xe8]
+;   stur x22, [sp, #0xf0]
+;   stur x23, [sp, #0xf8]
+;   str x24, [sp, #0x100]
+;   str x25, [sp, #0x108]
+;   mov x10, x2
+;   ldur x2, [sp]
 ;   add sp, sp, #0x10
+;   ldp x19, x20, [sp], #0x10
+;   ldp x21, x22, [sp], #0x10
+;   ldp x23, x24, [sp], #0x10
+;   ldp x25, x26, [sp], #0x10
+;   ldp x27, x28, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
-;   br x0
+;   br x10
 
diff --git a/cranelift/filetests/filetests/isa/aarch64/return-call.clif b/cranelift/filetests/filetests/isa/aarch64/return-call.clif
index cd00960f1..3f8f7d20f 100644
--- a/cranelift/filetests/filetests/isa/aarch64/return-call.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/return-call.clif
@@ -176,10 +176,28 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x9, [sp, #16]
-;   ldr x2, [sp, #24]
+;   ldr x7, [sp, #16]
+;   ldr x9, [sp, #24]
+;   ldr x11, [sp, #32]
+;   ldr x13, [sp, #40]
+;   ldr x15, [sp, #48]
+;   ldr x1, [sp, #56]
+;   ldr x3, [sp, #64]
+;   ldr x5, [sp, #72]
+;   ldr x7, [sp, #80]
+;   ldr x9, [sp, #88]
+;   ldr x11, [sp, #96]
+;   ldr x13, [sp, #104]
+;   ldr x15, [sp, #112]
+;   ldr x1, [sp, #120]
+;   ldr x3, [sp, #128]
+;   ldr x5, [sp, #136]
+;   ldr x7, [sp, #144]
+;   ldr x9, [sp, #152]
+;   ldr x11, [sp, #160]
+;   ldr x2, [sp, #168]
 ;   ldp fp, lr, [sp], #16
-;   add sp, sp, #16
+;   add sp, sp, #160
 ;   ret
 ;
 ; Disassembled:
@@ -187,10 +205,28 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x9, [sp, #0x10]
-;   ldur x2, [sp, #0x18]
+;   ldur x7, [sp, #0x10]
+;   ldur x9, [sp, #0x18]
+;   ldur x11, [sp, #0x20]
+;   ldur x13, [sp, #0x28]
+;   ldur x15, [sp, #0x30]
+;   ldur x1, [sp, #0x38]
+;   ldur x3, [sp, #0x40]
+;   ldur x5, [sp, #0x48]
+;   ldur x7, [sp, #0x50]
+;   ldur x9, [sp, #0x58]
+;   ldur x11, [sp, #0x60]
+;   ldur x13, [sp, #0x68]
+;   ldur x15, [sp, #0x70]
+;   ldur x1, [sp, #0x78]
+;   ldur x3, [sp, #0x80]
+;   ldur x5, [sp, #0x88]
+;   ldur x7, [sp, #0x90]
+;   ldur x9, [sp, #0x98]
+;   ldur x11, [sp, #0xa0]
+;   ldur x2, [sp, #0xa8]
 ;   ldp x29, x30, [sp], #0x10
-;   add sp, sp, #0x10
+;   add sp, sp, #0xa0
 ;   ret
 
 function %tail_caller_stack_args() -> i64 tail {
@@ -229,10 +265,15 @@ block0:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
-;   sub sp, sp, #16
-;   ldr fp, [sp, #16]
+;   sub sp, sp, #160
+;   ldr fp, [sp, #160]
 ;   stp fp, lr, [sp]
 ;   mov fp, sp
+;   stp x27, x28, [sp, #-16]!
+;   stp x25, x26, [sp, #-16]!
+;   stp x23, x24, [sp, #-16]!
+;   stp x21, x22, [sp, #-16]!
+;   stp x19, x20, [sp, #-16]!
 ; block0:
 ;   movz x2, #10
 ;   movz x3, #15
@@ -240,74 +281,120 @@ block0:
 ;   movz x5, #25
 ;   movz x6, #30
 ;   movz x7, #35
-;   movz x8, #40
-;   movz x9, #45
-;   movz x10, #50
-;   movz x11, #55
-;   movz x12, #60
-;   movz x13, #65
-;   movz x14, #70
-;   movz x15, #75
-;   movz x19, #80
-;   movz x20, #85
-;   movz x21, #90
-;   movz x22, #95
-;   movz x23, #100
-;   movz x24, #105
-;   movz x25, #110
-;   movz x26, #115
-;   movz x27, #120
-;   movz x28, #125
-;   movz x0, #130
-;   movz x1, #135
-;   str x0, [sp, #16]
-;   str x1, [sp, #24]
-;   load_ext_name x0, TestCase(%tail_callee_stack_args)+0
-;   return_call_ind x0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
+;   movz x10, #40
+;   movz x11, #45
+;   movz x12, #50
+;   movz x13, #55
+;   movz x14, #60
+;   movz x15, #65
+;   movz x0, #70
+;   movz x1, #75
+;   movz x8, #80
+;   movz x9, #85
+;   movz x26, #90
+;   movz x27, #95
+;   movz x28, #100
+;   movz x21, #105
+;   movz x19, #110
+;   movz x20, #115
+;   movz x22, #120
+;   movz x23, #125
+;   movz x24, #130
+;   movz x25, #135
+;   str x10, [sp, #96]
+;   str x11, [sp, #104]
+;   str x12, [sp, #112]
+;   str x13, [sp, #120]
+;   str x14, [sp, #128]
+;   str x15, [sp, #136]
+;   str x0, [sp, #144]
+;   str x1, [sp, #152]
+;   str x8, [sp, #160]
+;   str x9, [sp, #168]
+;   str x26, [sp, #176]
+;   str x27, [sp, #184]
+;   str x28, [sp, #192]
+;   str x21, [sp, #200]
+;   str x19, [sp, #208]
+;   str x20, [sp, #216]
+;   str x22, [sp, #224]
+;   str x23, [sp, #232]
+;   str x24, [sp, #240]
+;   str x25, [sp, #248]
+;   load_ext_name x14, TestCase(%tail_callee_stack_args)+0
+;   return_call_ind x14 new_stack_arg_size:160 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
-;   sub sp, sp, #0x10
-;   ldur x29, [sp, #0x10]
+;   sub sp, sp, #0xa0
+;   ldur x29, [sp, #0xa0]
 ;   stp x29, x30, [sp]
 ;   mov x29, sp
-; block1: ; offset 0x18
+;   stp x27, x28, [sp, #-0x10]!
+;   stp x25, x26, [sp, #-0x10]!
+;   stp x23, x24, [sp, #-0x10]!
+;   stp x21, x22, [sp, #-0x10]!
+;   stp x19, x20, [sp, #-0x10]!
+; block1: ; offset 0x2c
 ;   mov x2, #0xa
 ;   mov x3, #0xf
 ;   mov x4, #0x14
 ;   mov x5, #0x19
 ;   mov x6, #0x1e
 ;   mov x7, #0x23
-;   mov x8, #0x28
-;   mov x9, #0x2d
-;   mov x10, #0x32
-;   mov x11, #0x37
-;   mov x12, #0x3c
-;   mov x13, #0x41
-;   mov x14, #0x46
-;   mov x15, #0x4b
-;   mov x19, #0x50
-;   mov x20, #0x55
-;   mov x21, #0x5a
-;   mov x22, #0x5f
-;   mov x23, #0x64
-;   mov x24, #0x69
-;   mov x25, #0x6e
-;   mov x26, #0x73
-;   mov x27, #0x78
-;   mov x28, #0x7d
-;   mov x0, #0x82
-;   mov x1, #0x87
-;   stur x0, [sp, #0x10]
-;   stur x1, [sp, #0x18]
-;   ldr x0, #0x90
-;   b #0x98
+;   mov x10, #0x28
+;   mov x11, #0x2d
+;   mov x12, #0x32
+;   mov x13, #0x37
+;   mov x14, #0x3c
+;   mov x15, #0x41
+;   mov x0, #0x46
+;   mov x1, #0x4b
+;   mov x8, #0x50
+;   mov x9, #0x55
+;   mov x26, #0x5a
+;   mov x27, #0x5f
+;   mov x28, #0x64
+;   mov x21, #0x69
+;   mov x19, #0x6e
+;   mov x20, #0x73
+;   mov x22, #0x78
+;   mov x23, #0x7d
+;   mov x24, #0x82
+;   mov x25, #0x87
+;   stur x10, [sp, #0x60]
+;   stur x11, [sp, #0x68]
+;   stur x12, [sp, #0x70]
+;   stur x13, [sp, #0x78]
+;   stur x14, [sp, #0x80]
+;   stur x15, [sp, #0x88]
+;   stur x0, [sp, #0x90]
+;   stur x1, [sp, #0x98]
+;   stur x8, [sp, #0xa0]
+;   stur x9, [sp, #0xa8]
+;   stur x26, [sp, #0xb0]
+;   stur x27, [sp, #0xb8]
+;   stur x28, [sp, #0xc0]
+;   stur x21, [sp, #0xc8]
+;   stur x19, [sp, #0xd0]
+;   stur x20, [sp, #0xd8]
+;   stur x22, [sp, #0xe0]
+;   stur x23, [sp, #0xe8]
+;   stur x24, [sp, #0xf0]
+;   stur x25, [sp, #0xf8]
+;   ldr x14, #0xec
+;   b #0xf4
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %tail_callee_stack_args 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
+;   ldp x19, x20, [sp], #0x10
+;   ldp x21, x22, [sp], #0x10
+;   ldp x23, x24, [sp], #0x10
+;   ldp x25, x26, [sp], #0x10
+;   ldp x27, x28, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
-;   br x0
+;   br x14
 
 ;;;; Test diff blocks with diff return calls with diff # of stack args ;;;;;;;;;
 
@@ -320,10 +407,28 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x9, [sp, #16]
-;   ldr x2, [sp, #24]
+;   ldr x7, [sp, #16]
+;   ldr x9, [sp, #24]
+;   ldr x11, [sp, #32]
+;   ldr x13, [sp, #40]
+;   ldr x15, [sp, #48]
+;   ldr x1, [sp, #56]
+;   ldr x3, [sp, #64]
+;   ldr x5, [sp, #72]
+;   ldr x7, [sp, #80]
+;   ldr x9, [sp, #88]
+;   ldr x11, [sp, #96]
+;   ldr x13, [sp, #104]
+;   ldr x15, [sp, #112]
+;   ldr x1, [sp, #120]
+;   ldr x3, [sp, #128]
+;   ldr x5, [sp, #136]
+;   ldr x7, [sp, #144]
+;   ldr x9, [sp, #152]
+;   ldr x11, [sp, #160]
+;   ldr x2, [sp, #168]
 ;   ldp fp, lr, [sp], #16
-;   add sp, sp, #16
+;   add sp, sp, #160
 ;   ret
 ;
 ; Disassembled:
@@ -331,10 +436,28 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x9, [sp, #0x10]
-;   ldur x2, [sp, #0x18]
+;   ldur x7, [sp, #0x10]
+;   ldur x9, [sp, #0x18]
+;   ldur x11, [sp, #0x20]
+;   ldur x13, [sp, #0x28]
+;   ldur x15, [sp, #0x30]
+;   ldur x1, [sp, #0x38]
+;   ldur x3, [sp, #0x40]
+;   ldur x5, [sp, #0x48]
+;   ldur x7, [sp, #0x50]
+;   ldur x9, [sp, #0x58]
+;   ldur x11, [sp, #0x60]
+;   ldur x13, [sp, #0x68]
+;   ldur x15, [sp, #0x70]
+;   ldur x1, [sp, #0x78]
+;   ldur x3, [sp, #0x80]
+;   ldur x5, [sp, #0x88]
+;   ldur x7, [sp, #0x90]
+;   ldur x9, [sp, #0x98]
+;   ldur x11, [sp, #0xa0]
+;   ldur x2, [sp, #0xa8]
 ;   ldp x29, x30, [sp], #0x10
-;   add sp, sp, #0x10
+;   add sp, sp, #0xa0
 ;   ret
 
 function %different_callee2(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64) -> i64 tail {
@@ -346,11 +469,29 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x9, [sp, #16]
-;   ldr x11, [sp, #24]
-;   ldr x2, [sp, #32]
+;   ldr x7, [sp, #16]
+;   ldr x9, [sp, #24]
+;   ldr x11, [sp, #32]
+;   ldr x13, [sp, #40]
+;   ldr x15, [sp, #48]
+;   ldr x1, [sp, #56]
+;   ldr x3, [sp, #64]
+;   ldr x5, [sp, #72]
+;   ldr x7, [sp, #80]
+;   ldr x9, [sp, #88]
+;   ldr x11, [sp, #96]
+;   ldr x13, [sp, #104]
+;   ldr x15, [sp, #112]
+;   ldr x1, [sp, #120]
+;   ldr x3, [sp, #128]
+;   ldr x5, [sp, #136]
+;   ldr x7, [sp, #144]
+;   ldr x9, [sp, #152]
+;   ldr x11, [sp, #160]
+;   ldr x13, [sp, #168]
+;   ldr x2, [sp, #176]
 ;   ldp fp, lr, [sp], #16
-;   add sp, sp, #32
+;   add sp, sp, #176
 ;   ret
 ;
 ; Disassembled:
@@ -358,11 +499,29 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x9, [sp, #0x10]
-;   ldur x11, [sp, #0x18]
-;   ldur x2, [sp, #0x20]
+;   ldur x7, [sp, #0x10]
+;   ldur x9, [sp, #0x18]
+;   ldur x11, [sp, #0x20]
+;   ldur x13, [sp, #0x28]
+;   ldur x15, [sp, #0x30]
+;   ldur x1, [sp, #0x38]
+;   ldur x3, [sp, #0x40]
+;   ldur x5, [sp, #0x48]
+;   ldur x7, [sp, #0x50]
+;   ldur x9, [sp, #0x58]
+;   ldur x11, [sp, #0x60]
+;   ldur x13, [sp, #0x68]
+;   ldur x15, [sp, #0x70]
+;   ldur x1, [sp, #0x78]
+;   ldur x3, [sp, #0x80]
+;   ldur x5, [sp, #0x88]
+;   ldur x7, [sp, #0x90]
+;   ldur x9, [sp, #0x98]
+;   ldur x11, [sp, #0xa0]
+;   ldur x13, [sp, #0xa8]
+;   ldur x2, [sp, #0xb0]
 ;   ldp x29, x30, [sp], #0x10
-;   add sp, sp, #0x20
+;   add sp, sp, #0xb0
 ;   ret
 
 function %caller_of_different_callees(i64) -> i64 tail {
@@ -409,120 +568,208 @@ block2:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
-;   sub sp, sp, #32
-;   ldr fp, [sp, #32]
+;   sub sp, sp, #176
+;   ldr fp, [sp, #176]
 ;   stp fp, lr, [sp]
 ;   mov fp, sp
+;   stp x27, x28, [sp, #-16]!
+;   stp x25, x26, [sp, #-16]!
+;   stp x23, x24, [sp, #-16]!
+;   stp x21, x22, [sp, #-16]!
+;   stp x19, x20, [sp, #-16]!
 ;   sub sp, sp, #16
 ; block0:
-;   str x2, [sp]
-;   movz x2, #10
-;   str x2, [sp, #8]
+;   movz x14, #10
+;   str x14, [sp]
 ;   movz x3, #15
 ;   movz x4, #20
 ;   movz x5, #25
 ;   movz x6, #30
 ;   movz x7, #35
-;   movz x8, #40
-;   movz x9, #45
-;   movz x10, #50
-;   movz x11, #55
-;   movz x12, #60
-;   movz x13, #65
-;   movz x14, #70
-;   movz x15, #75
-;   movz x19, #80
-;   movz x20, #85
-;   movz x21, #90
-;   movz x22, #95
-;   movz x23, #100
-;   movz x24, #105
-;   movz x25, #110
-;   movz x26, #115
-;   movz x27, #120
-;   movz x28, #125
-;   movz x1, #130
-;   movz x0, #135
-;   ldr x2, [sp]
+;   movz x21, #40
+;   movz x28, #45
+;   movz x27, #50
+;   movz x26, #55
+;   movz x25, #60
+;   movz x24, #65
+;   movz x23, #70
+;   movz x22, #75
+;   movz x20, #80
+;   movz x19, #85
+;   movz x13, #90
+;   movz x12, #95
+;   movz x11, #100
+;   movz x10, #105
+;   movz x9, #110
+;   movz x8, #115
+;   movz x1, #120
+;   movz x0, #125
+;   movz x15, #130
+;   movz x14, #135
 ;   cbnz x2, label2 ; b label1
 ; block1:
 ;   movz x2, #140
-;   str x1, [sp, #32]
-;   str x0, [sp, #40]
-;   str x2, [sp, #48]
-;   load_ext_name x0, TestCase(%different_callee2)+0
-;   ldr x2, [sp, #8]
-;   return_call_ind x0 new_stack_arg_size:32 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
+;   str x21, [sp, #112]
+;   str x28, [sp, #120]
+;   str x27, [sp, #128]
+;   str x26, [sp, #136]
+;   str x25, [sp, #144]
+;   str x24, [sp, #152]
+;   str x23, [sp, #160]
+;   str x22, [sp, #168]
+;   str x20, [sp, #176]
+;   str x19, [sp, #184]
+;   str x13, [sp, #192]
+;   str x12, [sp, #200]
+;   str x11, [sp, #208]
+;   str x10, [sp, #216]
+;   str x9, [sp, #224]
+;   str x8, [sp, #232]
+;   str x1, [sp, #240]
+;   str x0, [sp, #248]
+;   str x15, [sp, #256]
+;   str x14, [sp, #264]
+;   str x2, [sp, #272]
+;   load_ext_name x8, TestCase(%different_callee2)+0
+;   ldr x2, [sp]
+;   return_call_ind x8 new_stack_arg_size:176 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7
 ; block2:
-;   ldr x2, [sp, #8]
-;   str x1, [sp, #48]
-;   str x0, [sp, #56]
-;   load_ext_name x0, TestCase(%different_callee1)+0
-;   return_call_ind x0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
+;   ldr x2, [sp]
+;   str x21, [sp, #128]
+;   str x28, [sp, #136]
+;   str x27, [sp, #144]
+;   str x26, [sp, #152]
+;   str x25, [sp, #160]
+;   str x24, [sp, #168]
+;   str x23, [sp, #176]
+;   str x22, [sp, #184]
+;   str x20, [sp, #192]
+;   str x19, [sp, #200]
+;   str x13, [sp, #208]
+;   str x12, [sp, #216]
+;   str x11, [sp, #224]
+;   str x10, [sp, #232]
+;   str x9, [sp, #240]
+;   str x8, [sp, #248]
+;   str x1, [sp, #256]
+;   str x0, [sp, #264]
+;   str x15, [sp, #272]
+;   str x14, [sp, #280]
+;   load_ext_name x9, TestCase(%different_callee1)+0
+;   return_call_ind x9 new_stack_arg_size:160 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
-;   sub sp, sp, #0x20
-;   ldur x29, [sp, #0x20]
+;   sub sp, sp, #0xb0
+;   ldur x29, [sp, #0xb0]
 ;   stp x29, x30, [sp]
 ;   mov x29, sp
+;   stp x27, x28, [sp, #-0x10]!
+;   stp x25, x26, [sp, #-0x10]!
+;   stp x23, x24, [sp, #-0x10]!
+;   stp x21, x22, [sp, #-0x10]!
+;   stp x19, x20, [sp, #-0x10]!
 ;   sub sp, sp, #0x10
-; block1: ; offset 0x1c
-;   stur x2, [sp]
-;   mov x2, #0xa
-;   stur x2, [sp, #8]
+; block1: ; offset 0x30
+;   mov x14, #0xa
+;   stur x14, [sp]
 ;   mov x3, #0xf
 ;   mov x4, #0x14
 ;   mov x5, #0x19
 ;   mov x6, #0x1e
 ;   mov x7, #0x23
-;   mov x8, #0x28
-;   mov x9, #0x2d
-;   mov x10, #0x32
-;   mov x11, #0x37
-;   mov x12, #0x3c
-;   mov x13, #0x41
-;   mov x14, #0x46
-;   mov x15, #0x4b
-;   mov x19, #0x50
-;   mov x20, #0x55
-;   mov x21, #0x5a
-;   mov x22, #0x5f
-;   mov x23, #0x64
-;   mov x24, #0x69
-;   mov x25, #0x6e
-;   mov x26, #0x73
-;   mov x27, #0x78
-;   mov x28, #0x7d
-;   mov x1, #0x82
-;   mov x0, #0x87
-;   ldur x2, [sp]
-;   cbnz x2, #0xc4
-; block2: ; offset 0x94
+;   mov x21, #0x28
+;   mov x28, #0x2d
+;   mov x27, #0x32
+;   mov x26, #0x37
+;   mov x25, #0x3c
+;   mov x24, #0x41
+;   mov x23, #0x46
+;   mov x22, #0x4b
+;   mov x20, #0x50
+;   mov x19, #0x55
+;   mov x13, #0x5a
+;   mov x12, #0x5f
+;   mov x11, #0x64
+;   mov x10, #0x69
+;   mov x9, #0x6e
+;   mov x8, #0x73
+;   mov x1, #0x78
+;   mov x0, #0x7d
+;   mov x15, #0x82
+;   mov x14, #0x87
+;   cbnz x2, #0x12c
+; block2: ; offset 0xa0
 ;   mov x2, #0x8c
-;   stur x1, [sp, #0x20]
-;   stur x0, [sp, #0x28]
-;   stur x2, [sp, #0x30]
-;   ldr x0, #0xac
-;   b #0xb4
+;   stur x21, [sp, #0x70]
+;   stur x28, [sp, #0x78]
+;   stur x27, [sp, #0x80]
+;   stur x26, [sp, #0x88]
+;   stur x25, [sp, #0x90]
+;   stur x24, [sp, #0x98]
+;   stur x23, [sp, #0xa0]
+;   stur x22, [sp, #0xa8]
+;   stur x20, [sp, #0xb0]
+;   stur x19, [sp, #0xb8]
+;   stur x13, [sp, #0xc0]
+;   stur x12, [sp, #0xc8]
+;   stur x11, [sp, #0xd0]
+;   stur x10, [sp, #0xd8]
+;   stur x9, [sp, #0xe0]
+;   stur x8, [sp, #0xe8]
+;   stur x1, [sp, #0xf0]
+;   stur x0, [sp, #0xf8]
+;   str x15, [sp, #0x100]
+;   str x14, [sp, #0x108]
+;   str x2, [sp, #0x110]
+;   ldr x8, #0x100
+;   b #0x108
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %different_callee2 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldur x2, [sp, #8]
+;   ldur x2, [sp]
 ;   add sp, sp, #0x10
+;   ldp x19, x20, [sp], #0x10
+;   ldp x21, x22, [sp], #0x10
+;   ldp x23, x24, [sp], #0x10
+;   ldp x25, x26, [sp], #0x10
+;   ldp x27, x28, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
-;   br x0
-; block3: ; offset 0xc4
-;   ldur x2, [sp, #8]
-;   stur x1, [sp, #0x30]
-;   stur x0, [sp, #0x38]
-;   ldr x0, #0xd8
-;   b #0xe0
+;   br x8
+; block3: ; offset 0x12c
+;   ldur x2, [sp]
+;   stur x21, [sp, #0x80]
+;   stur x28, [sp, #0x88]
+;   stur x27, [sp, #0x90]
+;   stur x26, [sp, #0x98]
+;   stur x25, [sp, #0xa0]
+;   stur x24, [sp, #0xa8]
+;   stur x23, [sp, #0xb0]
+;   stur x22, [sp, #0xb8]
+;   stur x20, [sp, #0xc0]
+;   stur x19, [sp, #0xc8]
+;   stur x13, [sp, #0xd0]
+;   stur x12, [sp, #0xd8]
+;   stur x11, [sp, #0xe0]
+;   stur x10, [sp, #0xe8]
+;   stur x9, [sp, #0xf0]
+;   stur x8, [sp, #0xf8]
+;   str x1, [sp, #0x100]
+;   str x0, [sp, #0x108]
+;   str x15, [sp, #0x110]
+;   str x14, [sp, #0x118]
+;   ldr x9, #0x188
+;   b #0x190
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %different_callee1 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
 ;   add sp, sp, #0x10
+;   ldp x19, x20, [sp], #0x10
+;   ldp x21, x22, [sp], #0x10
+;   ldp x23, x24, [sp], #0x10
+;   ldp x25, x26, [sp], #0x10
+;   ldp x27, x28, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
 ;   add sp, sp, #0x10
-;   br x0
+;   br x9
 
diff --git a/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif b/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif
index a68287270..f90085e27 100644
--- a/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif
@@ -12,10 +12,28 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x9, [sp, #16]
-;   ldr x2, [sp, #24]
+;   ldr x7, [sp, #16]
+;   ldr x9, [sp, #24]
+;   ldr x11, [sp, #32]
+;   ldr x13, [sp, #40]
+;   ldr x15, [sp, #48]
+;   ldr x1, [sp, #56]
+;   ldr x3, [sp, #64]
+;   ldr x5, [sp, #72]
+;   ldr x7, [sp, #80]
+;   ldr x9, [sp, #88]
+;   ldr x11, [sp, #96]
+;   ldr x13, [sp, #104]
+;   ldr x15, [sp, #112]
+;   ldr x1, [sp, #120]
+;   ldr x3, [sp, #128]
+;   ldr x5, [sp, #136]
+;   ldr x7, [sp, #144]
+;   ldr x9, [sp, #152]
+;   ldr x11, [sp, #160]
+;   ldr x2, [sp, #168]
 ;   ldp fp, lr, [sp], #16
-;   add sp, sp, #16
+;   add sp, sp, #160
 ;   ret
 ;
 ; Disassembled:
@@ -23,10 +41,28 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x9, [sp, #0x10]
-;   ldur x2, [sp, #0x18]
+;   ldur x7, [sp, #0x10]
+;   ldur x9, [sp, #0x18]
+;   ldur x11, [sp, #0x20]
+;   ldur x13, [sp, #0x28]
+;   ldur x15, [sp, #0x30]
+;   ldur x1, [sp, #0x38]
+;   ldur x3, [sp, #0x40]
+;   ldur x5, [sp, #0x48]
+;   ldur x7, [sp, #0x50]
+;   ldur x9, [sp, #0x58]
+;   ldur x11, [sp, #0x60]
+;   ldur x13, [sp, #0x68]
+;   ldur x15, [sp, #0x70]
+;   ldur x1, [sp, #0x78]
+;   ldur x3, [sp, #0x80]
+;   ldur x5, [sp, #0x88]
+;   ldur x7, [sp, #0x90]
+;   ldur x9, [sp, #0x98]
+;   ldur x11, [sp, #0xa0]
+;   ldur x2, [sp, #0xa8]
 ;   ldp x29, x30, [sp], #0x10
-;   add sp, sp, #0x10
+;   add sp, sp, #0xa0
 ;   ret
 
 function %tail_caller_stack_args() -> i64 tail {
@@ -66,8 +102,13 @@ block0:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
-;   sub sp, sp, #16
-;   virtual_sp_offset_adjust 16
+;   stp x27, x28, [sp, #-16]!
+;   stp x25, x26, [sp, #-16]!
+;   stp x23, x24, [sp, #-16]!
+;   stp x21, x22, [sp, #-16]!
+;   stp x19, x20, [sp, #-16]!
+;   sub sp, sp, #160
+;   virtual_sp_offset_adjust 160
 ; block0:
 ;   movz x2, #10
 ;   movz x3, #15
@@ -75,33 +116,56 @@ block0:
 ;   movz x5, #25
 ;   movz x6, #30
 ;   movz x7, #35
-;   movz x8, #40
-;   movz x9, #45
-;   movz x10, #50
-;   movz x11, #55
-;   movz x12, #60
-;   movz x13, #65
-;   movz x14, #70
-;   movz x15, #75
-;   movz x19, #80
-;   movz x20, #85
-;   movz x21, #90
-;   movz x22, #95
-;   movz x23, #100
-;   movz x24, #105
-;   movz x25, #110
-;   movz x26, #115
-;   movz x27, #120
-;   movz x28, #125
-;   movz x0, #130
-;   movz x1, #135
-;   str x0, [sp]
-;   str x1, [sp, #8]
+;   movz x11, #40
+;   movz x12, #45
+;   movz x13, #50
+;   movz x14, #55
+;   movz x15, #60
+;   movz x0, #65
+;   movz x1, #70
+;   movz x8, #75
+;   movz x9, #80
+;   movz x10, #85
+;   movz x27, #90
+;   movz x28, #95
+;   movz x21, #100
+;   movz x19, #105
+;   movz x20, #110
+;   movz x22, #115
+;   movz x23, #120
+;   movz x24, #125
+;   movz x25, #130
+;   movz x26, #135
+;   str x11, [sp]
+;   str x12, [sp, #8]
+;   str x13, [sp, #16]
+;   str x14, [sp, #24]
+;   str x15, [sp, #32]
+;   str x0, [sp, #40]
+;   str x1, [sp, #48]
+;   str x8, [sp, #56]
+;   str x9, [sp, #64]
+;   str x10, [sp, #72]
+;   str x27, [sp, #80]
+;   str x28, [sp, #88]
+;   str x21, [sp, #96]
+;   str x19, [sp, #104]
+;   str x20, [sp, #112]
+;   str x22, [sp, #120]
+;   str x23, [sp, #128]
+;   str x24, [sp, #136]
+;   str x25, [sp, #144]
+;   str x26, [sp, #152]
 ;   load_ext_name x1, TestCase(%tail_callee_stack_args)+0
 ;   blr x1
-;   sub sp, sp, #16
-;   virtual_sp_offset_adjust 16
-;   add sp, sp, #16
+;   sub sp, sp, #160
+;   virtual_sp_offset_adjust 160
+;   add sp, sp, #160
+;   ldp x19, x20, [sp], #16
+;   ldp x21, x22, [sp], #16
+;   ldp x23, x24, [sp], #16
+;   ldp x25, x26, [sp], #16
+;   ldp x27, x28, [sp], #16
 ;   ldp fp, lr, [sp], #16
 ;   ret
 ;
@@ -109,43 +173,71 @@ block0:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
-;   sub sp, sp, #0x10
-; block1: ; offset 0xc
+;   stp x27, x28, [sp, #-0x10]!
+;   stp x25, x26, [sp, #-0x10]!
+;   stp x23, x24, [sp, #-0x10]!
+;   stp x21, x22, [sp, #-0x10]!
+;   stp x19, x20, [sp, #-0x10]!
+;   sub sp, sp, #0xa0
+; block1: ; offset 0x20
 ;   mov x2, #0xa
 ;   mov x3, #0xf
 ;   mov x4, #0x14
 ;   mov x5, #0x19
 ;   mov x6, #0x1e
 ;   mov x7, #0x23
-;   mov x8, #0x28
-;   mov x9, #0x2d
-;   mov x10, #0x32
-;   mov x11, #0x37
-;   mov x12, #0x3c
-;   mov x13, #0x41
-;   mov x14, #0x46
-;   mov x15, #0x4b
-;   mov x19, #0x50
-;   mov x20, #0x55
-;   mov x21, #0x5a
-;   mov x22, #0x5f
-;   mov x23, #0x64
-;   mov x24, #0x69
-;   mov x25, #0x6e
-;   mov x26, #0x73
-;   mov x27, #0x78
-;   mov x28, #0x7d
-;   mov x0, #0x82
-;   mov x1, #0x87
-;   stur x0, [sp]
-;   stur x1, [sp, #8]
-;   ldr x1, #0x84
-;   b #0x8c
+;   mov x11, #0x28
+;   mov x12, #0x2d
+;   mov x13, #0x32
+;   mov x14, #0x37
+;   mov x15, #0x3c
+;   mov x0, #0x41
+;   mov x1, #0x46
+;   mov x8, #0x4b
+;   mov x9, #0x50
+;   mov x10, #0x55
+;   mov x27, #0x5a
+;   mov x28, #0x5f
+;   mov x21, #0x64
+;   mov x19, #0x69
+;   mov x20, #0x6e
+;   mov x22, #0x73
+;   mov x23, #0x78
+;   mov x24, #0x7d
+;   mov x25, #0x82
+;   mov x26, #0x87
+;   stur x11, [sp]
+;   stur x12, [sp, #8]
+;   stur x13, [sp, #0x10]
+;   stur x14, [sp, #0x18]
+;   stur x15, [sp, #0x20]
+;   stur x0, [sp, #0x28]
+;   stur x1, [sp, #0x30]
+;   stur x8, [sp, #0x38]
+;   stur x9, [sp, #0x40]
+;   stur x10, [sp, #0x48]
+;   stur x27, [sp, #0x50]
+;   stur x28, [sp, #0x58]
+;   stur x21, [sp, #0x60]
+;   stur x19, [sp, #0x68]
+;   stur x20, [sp, #0x70]
+;   stur x22, [sp, #0x78]
+;   stur x23, [sp, #0x80]
+;   stur x24, [sp, #0x88]
+;   stur x25, [sp, #0x90]
+;   stur x26, [sp, #0x98]
+;   ldr x1, #0xe0
+;   b #0xe8
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %tail_callee_stack_args 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
 ;   blr x1
-;   sub sp, sp, #0x10
-;   add sp, sp, #0x10
+;   sub sp, sp, #0xa0
+;   add sp, sp, #0xa0
+;   ldp x19, x20, [sp], #0x10
+;   ldp x21, x22, [sp], #0x10
+;   ldp x23, x24, [sp], #0x10
+;   ldp x25, x26, [sp], #0x10
+;   ldp x27, x28, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
 ;   ret
 
@@ -185,6 +277,11 @@ block0:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
+;   stp x27, x28, [sp, #-16]!
+;   stp x25, x26, [sp, #-16]!
+;   stp x23, x24, [sp, #-16]!
+;   stp x21, x22, [sp, #-16]!
+;   stp x19, x20, [sp, #-16]!
 ;   sub sp, sp, #16
 ; block0:
 ;   movz x2, #10
@@ -194,30 +291,53 @@ block0:
 ;   movz x5, #25
 ;   movz x6, #30
 ;   movz x7, #35
-;   movz x8, #40
-;   movz x9, #45
-;   movz x10, #50
-;   movz x11, #55
-;   movz x12, #60
-;   movz x13, #65
-;   movz x14, #70
-;   movz x15, #75
-;   movz x19, #80
-;   movz x20, #85
-;   movz x21, #90
-;   movz x22, #95
-;   movz x23, #100
-;   movz x24, #105
-;   movz x25, #110
-;   movz x26, #115
-;   movz x27, #120
-;   movz x28, #125
-;   movz x1, #130
+;   movz x11, #40
+;   movz x12, #45
+;   movz x13, #50
+;   movz x14, #55
+;   movz x15, #60
+;   movz x1, #65
+;   movz x8, #70
+;   movz x9, #75
+;   movz x10, #80
+;   movz x27, #85
+;   movz x28, #90
+;   movz x21, #95
+;   movz x19, #100
+;   movz x20, #105
+;   movz x22, #110
+;   movz x23, #115
+;   movz x24, #120
+;   movz x25, #125
+;   movz x26, #130
 ;   movz x2, #135
-;   str x1, [x0]
-;   str x2, [x0, #8]
+;   str x11, [x0]
+;   str x12, [x0, #8]
+;   str x13, [x0, #16]
+;   str x14, [x0, #24]
+;   str x15, [x0, #32]
+;   str x1, [x0, #40]
+;   str x8, [x0, #48]
+;   str x9, [x0, #56]
+;   str x10, [x0, #64]
+;   str x27, [x0, #72]
+;   str x28, [x0, #80]
+;   str x21, [x0, #88]
+;   str x19, [x0, #96]
+;   str x20, [x0, #104]
+;   str x22, [x0, #112]
+;   str x23, [x0, #120]
+;   str x24, [x0, #128]
+;   str x25, [x0, #136]
+;   str x26, [x0, #144]
+;   str x2, [x0, #152]
 ;   ldr x2, [sp]
 ;   add sp, sp, #16
+;   ldp x19, x20, [sp], #16
+;   ldp x21, x22, [sp], #16
+;   ldp x23, x24, [sp], #16
+;   ldp x25, x26, [sp], #16
+;   ldp x27, x28, [sp], #16
 ;   ldp fp, lr, [sp], #16
 ;   ret
 ;
@@ -225,8 +345,13 @@ block0:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
+;   stp x27, x28, [sp, #-0x10]!
+;   stp x25, x26, [sp, #-0x10]!
+;   stp x23, x24, [sp, #-0x10]!
+;   stp x21, x22, [sp, #-0x10]!
+;   stp x19, x20, [sp, #-0x10]!
 ;   sub sp, sp, #0x10
-; block1: ; offset 0xc
+; block1: ; offset 0x20
 ;   mov x2, #0xa
 ;   stur x2, [sp]
 ;   mov x3, #0xf
@@ -234,30 +359,53 @@ block0:
 ;   mov x5, #0x19
 ;   mov x6, #0x1e
 ;   mov x7, #0x23
-;   mov x8, #0x28
-;   mov x9, #0x2d
-;   mov x10, #0x32
-;   mov x11, #0x37
-;   mov x12, #0x3c
-;   mov x13, #0x41
-;   mov x14, #0x46
-;   mov x15, #0x4b
-;   mov x19, #0x50
-;   mov x20, #0x55
-;   mov x21, #0x5a
-;   mov x22, #0x5f
-;   mov x23, #0x64
-;   mov x24, #0x69
-;   mov x25, #0x6e
-;   mov x26, #0x73
-;   mov x27, #0x78
-;   mov x28, #0x7d
-;   mov x1, #0x82
+;   mov x11, #0x28
+;   mov x12, #0x2d
+;   mov x13, #0x32
+;   mov x14, #0x37
+;   mov x15, #0x3c
+;   mov x1, #0x41
+;   mov x8, #0x46
+;   mov x9, #0x4b
+;   mov x10, #0x50
+;   mov x27, #0x55
+;   mov x28, #0x5a
+;   mov x21, #0x5f
+;   mov x19, #0x64
+;   mov x20, #0x69
+;   mov x22, #0x6e
+;   mov x23, #0x73
+;   mov x24, #0x78
+;   mov x25, #0x7d
+;   mov x26, #0x82
 ;   mov x2, #0x87
-;   stur x1, [x0]
-;   stur x2, [x0, #8]
+;   stur x11, [x0]
+;   stur x12, [x0, #8]
+;   stur x13, [x0, #0x10]
+;   stur x14, [x0, #0x18]
+;   stur x15, [x0, #0x20]
+;   stur x1, [x0, #0x28]
+;   stur x8, [x0, #0x30]
+;   stur x9, [x0, #0x38]
+;   stur x10, [x0, #0x40]
+;   stur x27, [x0, #0x48]
+;   stur x28, [x0, #0x50]
+;   stur x21, [x0, #0x58]
+;   stur x19, [x0, #0x60]
+;   stur x20, [x0, #0x68]
+;   stur x22, [x0, #0x70]
+;   stur x23, [x0, #0x78]
+;   stur x24, [x0, #0x80]
+;   stur x25, [x0, #0x88]
+;   stur x26, [x0, #0x90]
+;   stur x2, [x0, #0x98]
 ;   ldur x2, [sp]
 ;   add sp, sp, #0x10
+;   ldp x19, x20, [sp], #0x10
+;   ldp x21, x22, [sp], #0x10
+;   ldp x23, x24, [sp], #0x10
+;   ldp x25, x26, [sp], #0x10
+;   ldp x27, x28, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
 ;   ret
 
@@ -272,15 +420,33 @@ block0:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
-;   sub sp, sp, #16
-;   virtual_sp_offset_adjust 16
+;   sub sp, sp, #160
+;   virtual_sp_offset_adjust 160
 ; block0:
 ;   mov x0, sp
 ;   load_ext_name x1, TestCase(%tail_callee_stack_rets)+0
 ;   blr x1
-;   ldr x11, [sp]
-;   ldr x2, [sp, #8]
-;   add sp, sp, #16
+;   ldr x9, [sp]
+;   ldr x11, [sp, #8]
+;   ldr x13, [sp, #16]
+;   ldr x15, [sp, #24]
+;   ldr x1, [sp, #32]
+;   ldr x3, [sp, #40]
+;   ldr x5, [sp, #48]
+;   ldr x7, [sp, #56]
+;   ldr x9, [sp, #64]
+;   ldr x11, [sp, #72]
+;   ldr x13, [sp, #80]
+;   ldr x15, [sp, #88]
+;   ldr x1, [sp, #96]
+;   ldr x3, [sp, #104]
+;   ldr x5, [sp, #112]
+;   ldr x7, [sp, #120]
+;   ldr x9, [sp, #128]
+;   ldr x11, [sp, #136]
+;   ldr x13, [sp, #144]
+;   ldr x2, [sp, #152]
+;   add sp, sp, #160
 ;   ldp fp, lr, [sp], #16
 ;   ret
 ;
@@ -288,7 +454,7 @@ block0:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
-;   sub sp, sp, #0x10
+;   sub sp, sp, #0xa0
 ; block1: ; offset 0xc
 ;   mov x0, sp
 ;   ldr x1, #0x18
@@ -296,9 +462,27 @@ block0:
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %tail_callee_stack_rets 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
 ;   blr x1
-;   ldur x11, [sp]
-;   ldur x2, [sp, #8]
-;   add sp, sp, #0x10
+;   ldur x9, [sp]
+;   ldur x11, [sp, #8]
+;   ldur x13, [sp, #0x10]
+;   ldur x15, [sp, #0x18]
+;   ldur x1, [sp, #0x20]
+;   ldur x3, [sp, #0x28]
+;   ldur x5, [sp, #0x30]
+;   ldur x7, [sp, #0x38]
+;   ldur x9, [sp, #0x40]
+;   ldur x11, [sp, #0x48]
+;   ldur x13, [sp, #0x50]
+;   ldur x15, [sp, #0x58]
+;   ldur x1, [sp, #0x60]
+;   ldur x3, [sp, #0x68]
+;   ldur x5, [sp, #0x70]
+;   ldur x7, [sp, #0x78]
+;   ldur x9, [sp, #0x80]
+;   ldur x11, [sp, #0x88]
+;   ldur x13, [sp, #0x90]
+;   ldur x2, [sp, #0x98]
+;   add sp, sp, #0xa0
 ;   ldp x29, x30, [sp], #0x10
 ;   ret
 
@@ -313,34 +497,126 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
+;   stp x27, x28, [sp, #-16]!
+;   stp x25, x26, [sp, #-16]!
+;   stp x23, x24, [sp, #-16]!
+;   stp x21, x22, [sp, #-16]!
+;   stp x19, x20, [sp, #-16]!
 ;   sub sp, sp, #16
 ; block0:
-;   str x9, [sp]
-;   ldr x9, [sp, #32]
-;   ldr x1, [sp, #40]
-;   str x9, [x0]
-;   str x1, [x0, #8]
-;   ldr x9, [sp]
+;   str x7, [sp]
+;   ldr x7, [sp, #112]
+;   ldr x19, [sp, #120]
+;   ldr x22, [sp, #128]
+;   ldr x24, [sp, #136]
+;   ldr x26, [sp, #144]
+;   ldr x28, [sp, #152]
+;   ldr x21, [sp, #160]
+;   ldr x20, [sp, #168]
+;   ldr x23, [sp, #176]
+;   ldr x25, [sp, #184]
+;   ldr x27, [sp, #192]
+;   ldr x14, [sp, #200]
+;   ldr x15, [sp, #208]
+;   ldr x1, [sp, #216]
+;   ldr x12, [sp, #224]
+;   ldr x10, [sp, #232]
+;   ldr x8, [sp, #240]
+;   ldr x9, [sp, #248]
+;   ldr x11, [sp, #256]
+;   ldr x13, [sp, #264]
+;   str x7, [x0]
+;   str x19, [x0, #8]
+;   str x22, [x0, #16]
+;   str x24, [x0, #24]
+;   str x26, [x0, #32]
+;   str x28, [x0, #40]
+;   str x21, [x0, #48]
+;   str x20, [x0, #56]
+;   str x23, [x0, #64]
+;   str x25, [x0, #72]
+;   str x27, [x0, #80]
+;   str x14, [x0, #88]
+;   str x15, [x0, #96]
+;   str x1, [x0, #104]
+;   str x12, [x0, #112]
+;   str x10, [x0, #120]
+;   str x8, [x0, #128]
+;   str x9, [x0, #136]
+;   str x11, [x0, #144]
+;   str x13, [x0, #152]
+;   ldr x7, [sp]
 ;   add sp, sp, #16
+;   ldp x19, x20, [sp], #16
+;   ldp x21, x22, [sp], #16
+;   ldp x23, x24, [sp], #16
+;   ldp x25, x26, [sp], #16
+;   ldp x27, x28, [sp], #16
 ;   ldp fp, lr, [sp], #16
-;   add sp, sp, #16
+;   add sp, sp, #160
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
+;   stp x27, x28, [sp, #-0x10]!
+;   stp x25, x26, [sp, #-0x10]!
+;   stp x23, x24, [sp, #-0x10]!
+;   stp x21, x22, [sp, #-0x10]!
+;   stp x19, x20, [sp, #-0x10]!
 ;   sub sp, sp, #0x10
-; block1: ; offset 0xc
-;   stur x9, [sp]
-;   ldur x9, [sp, #0x20]
-;   ldur x1, [sp, #0x28]
-;   stur x9, [x0]
-;   stur x1, [x0, #8]
-;   ldur x9, [sp]
+; block1: ; offset 0x20
+;   stur x7, [sp]
+;   ldur x7, [sp, #0x70]
+;   ldur x19, [sp, #0x78]
+;   ldur x22, [sp, #0x80]
+;   ldur x24, [sp, #0x88]
+;   ldur x26, [sp, #0x90]
+;   ldur x28, [sp, #0x98]
+;   ldur x21, [sp, #0xa0]
+;   ldur x20, [sp, #0xa8]
+;   ldur x23, [sp, #0xb0]
+;   ldur x25, [sp, #0xb8]
+;   ldur x27, [sp, #0xc0]
+;   ldur x14, [sp, #0xc8]
+;   ldur x15, [sp, #0xd0]
+;   ldur x1, [sp, #0xd8]
+;   ldur x12, [sp, #0xe0]
+;   ldur x10, [sp, #0xe8]
+;   ldur x8, [sp, #0xf0]
+;   ldur x9, [sp, #0xf8]
+;   ldr x11, [sp, #0x100]
+;   ldr x13, [sp, #0x108]
+;   stur x7, [x0]
+;   stur x19, [x0, #8]
+;   stur x22, [x0, #0x10]
+;   stur x24, [x0, #0x18]
+;   stur x26, [x0, #0x20]
+;   stur x28, [x0, #0x28]
+;   stur x21, [x0, #0x30]
+;   stur x20, [x0, #0x38]
+;   stur x23, [x0, #0x40]
+;   stur x25, [x0, #0x48]
+;   stur x27, [x0, #0x50]
+;   stur x14, [x0, #0x58]
+;   stur x15, [x0, #0x60]
+;   stur x1, [x0, #0x68]
+;   stur x12, [x0, #0x70]
+;   stur x10, [x0, #0x78]
+;   stur x8, [x0, #0x80]
+;   stur x9, [x0, #0x88]
+;   stur x11, [x0, #0x90]
+;   stur x13, [x0, #0x98]
+;   ldur x7, [sp]
 ;   add sp, sp, #0x10
+;   ldp x19, x20, [sp], #0x10
+;   ldp x21, x22, [sp], #0x10
+;   ldp x23, x24, [sp], #0x10
+;   ldp x25, x26, [sp], #0x10
+;   ldp x27, x28, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
-;   add sp, sp, #0x10
+;   add sp, sp, #0xa0
 ;   ret
 
 function %tail_caller_stack_args_and_rets() -> i64 tail {
@@ -380,8 +656,13 @@ block0:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
-;   sub sp, sp, #32
-;   virtual_sp_offset_adjust 32
+;   stp x27, x28, [sp, #-16]!
+;   stp x25, x26, [sp, #-16]!
+;   stp x23, x24, [sp, #-16]!
+;   stp x21, x22, [sp, #-16]!
+;   stp x19, x20, [sp, #-16]!
+;   sub sp, sp, #320
+;   virtual_sp_offset_adjust 320
 ; block0:
 ;   movz x2, #10
 ;   movz x3, #15
@@ -397,28 +678,69 @@ block0:
 ;   movz x13, #65
 ;   movz x14, #70
 ;   movz x15, #75
-;   movz x19, #80
-;   movz x20, #85
-;   movz x21, #90
-;   movz x22, #95
-;   movz x23, #100
-;   movz x24, #105
-;   movz x25, #110
-;   movz x26, #115
-;   movz x27, #120
-;   movz x28, #125
-;   movz x0, #130
-;   movz x1, #135
-;   str x0, [sp]
-;   str x1, [sp, #8]
-;   add x0, sp, #16
+;   movz x0, #80
+;   movz x1, #85
+;   movz x23, #90
+;   movz x24, #95
+;   movz x25, #100
+;   movz x26, #105
+;   movz x27, #110
+;   movz x28, #115
+;   movz x21, #120
+;   movz x19, #125
+;   movz x20, #130
+;   movz x22, #135
+;   str x8, [sp]
+;   str x9, [sp, #8]
+;   str x10, [sp, #16]
+;   str x11, [sp, #24]
+;   str x12, [sp, #32]
+;   str x13, [sp, #40]
+;   str x14, [sp, #48]
+;   str x15, [sp, #56]
+;   str x0, [sp, #64]
+;   str x1, [sp, #72]
+;   str x23, [sp, #80]
+;   str x24, [sp, #88]
+;   str x25, [sp, #96]
+;   str x26, [sp, #104]
+;   str x27, [sp, #112]
+;   str x28, [sp, #120]
+;   str x21, [sp, #128]
+;   str x19, [sp, #136]
+;   str x20, [sp, #144]
+;   str x22, [sp, #152]
+;   add x0, sp, #160
 ;   load_ext_name x1, TestCase(%tail_callee_stack_args_and_rets)+0
 ;   blr x1
-;   sub sp, sp, #16
-;   virtual_sp_offset_adjust 16
-;   ldr x9, [sp, #16]
-;   ldr x2, [sp, #24]
-;   add sp, sp, #32
+;   sub sp, sp, #160
+;   virtual_sp_offset_adjust 160
+;   ldr x9, [sp, #160]
+;   ldr x11, [sp, #168]
+;   ldr x13, [sp, #176]
+;   ldr x15, [sp, #184]
+;   ldr x1, [sp, #192]
+;   ldr x3, [sp, #200]
+;   ldr x5, [sp, #208]
+;   ldr x7, [sp, #216]
+;   ldr x9, [sp, #224]
+;   ldr x11, [sp, #232]
+;   ldr x13, [sp, #240]
+;   ldr x15, [sp, #248]
+;   ldr x1, [sp, #256]
+;   ldr x3, [sp, #264]
+;   ldr x5, [sp, #272]
+;   ldr x7, [sp, #280]
+;   ldr x9, [sp, #288]
+;   ldr x11, [sp, #296]
+;   ldr x13, [sp, #304]
+;   ldr x2, [sp, #312]
+;   add sp, sp, #320
+;   ldp x19, x20, [sp], #16
+;   ldp x21, x22, [sp], #16
+;   ldp x23, x24, [sp], #16
+;   ldp x25, x26, [sp], #16
+;   ldp x27, x28, [sp], #16
 ;   ldp fp, lr, [sp], #16
 ;   ret
 ;
@@ -426,8 +748,13 @@ block0:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
-;   sub sp, sp, #0x20
-; block1: ; offset 0xc
+;   stp x27, x28, [sp, #-0x10]!
+;   stp x25, x26, [sp, #-0x10]!
+;   stp x23, x24, [sp, #-0x10]!
+;   stp x21, x22, [sp, #-0x10]!
+;   stp x19, x20, [sp, #-0x10]!
+;   sub sp, sp, #0x140
+; block1: ; offset 0x20
 ;   mov x2, #0xa
 ;   mov x3, #0xf
 ;   mov x4, #0x14
@@ -442,30 +769,71 @@ block0:
 ;   mov x13, #0x41
 ;   mov x14, #0x46
 ;   mov x15, #0x4b
-;   mov x19, #0x50
-;   mov x20, #0x55
-;   mov x21, #0x5a
-;   mov x22, #0x5f
-;   mov x23, #0x64
-;   mov x24, #0x69
-;   mov x25, #0x6e
-;   mov x26, #0x73
-;   mov x27, #0x78
-;   mov x28, #0x7d
-;   mov x0, #0x82
-;   mov x1, #0x87
-;   stur x0, [sp]
-;   stur x1, [sp, #8]
-;   add x0, sp, #0x10
-;   ldr x1, #0x88
-;   b #0x90
+;   mov x0, #0x50
+;   mov x1, #0x55
+;   mov x23, #0x5a
+;   mov x24, #0x5f
+;   mov x25, #0x64
+;   mov x26, #0x69
+;   mov x27, #0x6e
+;   mov x28, #0x73
+;   mov x21, #0x78
+;   mov x19, #0x7d
+;   mov x20, #0x82
+;   mov x22, #0x87
+;   stur x8, [sp]
+;   stur x9, [sp, #8]
+;   stur x10, [sp, #0x10]
+;   stur x11, [sp, #0x18]
+;   stur x12, [sp, #0x20]
+;   stur x13, [sp, #0x28]
+;   stur x14, [sp, #0x30]
+;   stur x15, [sp, #0x38]
+;   stur x0, [sp, #0x40]
+;   stur x1, [sp, #0x48]
+;   stur x23, [sp, #0x50]
+;   stur x24, [sp, #0x58]
+;   stur x25, [sp, #0x60]
+;   stur x26, [sp, #0x68]
+;   stur x27, [sp, #0x70]
+;   stur x28, [sp, #0x78]
+;   stur x21, [sp, #0x80]
+;   stur x19, [sp, #0x88]
+;   stur x20, [sp, #0x90]
+;   stur x22, [sp, #0x98]
+;   add x0, sp, #0xa0
+;   ldr x1, #0xe4
+;   b #0xec
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %tail_callee_stack_args_and_rets 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
 ;   blr x1
-;   sub sp, sp, #0x10
-;   ldur x9, [sp, #0x10]
-;   ldur x2, [sp, #0x18]
-;   add sp, sp, #0x20
+;   sub sp, sp, #0xa0
+;   ldur x9, [sp, #0xa0]
+;   ldur x11, [sp, #0xa8]
+;   ldur x13, [sp, #0xb0]
+;   ldur x15, [sp, #0xb8]
+;   ldur x1, [sp, #0xc0]
+;   ldur x3, [sp, #0xc8]
+;   ldur x5, [sp, #0xd0]
+;   ldur x7, [sp, #0xd8]
+;   ldur x9, [sp, #0xe0]
+;   ldur x11, [sp, #0xe8]
+;   ldur x13, [sp, #0xf0]
+;   ldur x15, [sp, #0xf8]
+;   ldr x1, [sp, #0x100]
+;   ldr x3, [sp, #0x108]
+;   ldr x5, [sp, #0x110]
+;   ldr x7, [sp, #0x118]
+;   ldr x9, [sp, #0x120]
+;   ldr x11, [sp, #0x128]
+;   ldr x13, [sp, #0x130]
+;   ldr x2, [sp, #0x138]
+;   add sp, sp, #0x140
+;   ldp x19, x20, [sp], #0x10
+;   ldp x21, x22, [sp], #0x10
+;   ldp x23, x24, [sp], #0x10
+;   ldp x25, x26, [sp], #0x10
+;   ldp x27, x28, [sp], #0x10
 ;   ldp x29, x30, [sp], #0x10
 ;   ret