
This changes the save/restore procedures to save/restore registers one by one - to match the stack alignment for the ILP32E/LP64E ABIs, rather than the larger batches of the conventional ABIs. The implementations of the save routines are not tail-shared, to reduce the number of instructions. I think this also helps code size but I need to check this again. I would expect (but haven't measured) that the majority of functions compiled for the ILP32E/LP64E ABIs will in fact use both callee-saved registers, and therefore there are still savings to be had, but I think those can come later, with more data (especially if those changes are just to the instruction sequences we use to save the registers, rather than the number and alignment of how this is done). This is a potential break for all of the ILP32E/LP64E ABI - we may instead have to teach the compiler to emit the CFI information correctly for the grouping we already have implemented (because that grouping matches GCC). It depends on how intentional we think the grouping is in the original ILP32E/LP64E save/restore implementation was, and whether we think we can fix that now.
224 lines
5.5 KiB
ArmAsm
224 lines
5.5 KiB
ArmAsm
//===-- restore.S - restore up to 12 callee-save registers ----------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Multiple entry points depending on number of registers to restore
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// All of the entry points are in the same section since we rely on many of
|
|
// them falling through into each other and don't want the linker to
|
|
// accidentally split them up, garbage collect, or reorder them.
|
|
//
|
|
// For the conventional ABIs, entry points are grouped up into 2s for rv64 and
|
|
// 4s for rv32 since this is the minimum grouping which will maintain the
|
|
// required 16-byte stack alignment.
|
|
//
|
|
// For the ilp32e/lp64e abis, entry points are grouped into 1s, since this is
|
|
// the minimum grouping which will maintain the required 4-byte stack alignment.
|
|
|
|
.text
|
|
|
|
#if __riscv_xlen == 32
|
|
|
|
#ifndef __riscv_abi_rve
|
|
|
|
.globl __riscv_restore_12
|
|
.type __riscv_restore_12,@function
|
|
__riscv_restore_12:
|
|
lw s11, 12(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_11/10/9/8
|
|
|
|
.globl __riscv_restore_11
|
|
.type __riscv_restore_11,@function
|
|
.globl __riscv_restore_10
|
|
.type __riscv_restore_10,@function
|
|
.globl __riscv_restore_9
|
|
.type __riscv_restore_9,@function
|
|
.globl __riscv_restore_8
|
|
.type __riscv_restore_8,@function
|
|
__riscv_restore_11:
|
|
__riscv_restore_10:
|
|
__riscv_restore_9:
|
|
__riscv_restore_8:
|
|
lw s10, 0(sp)
|
|
lw s9, 4(sp)
|
|
lw s8, 8(sp)
|
|
lw s7, 12(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_7/6/5/4
|
|
|
|
.globl __riscv_restore_7
|
|
.type __riscv_restore_7,@function
|
|
.globl __riscv_restore_6
|
|
.type __riscv_restore_6,@function
|
|
.globl __riscv_restore_5
|
|
.type __riscv_restore_5,@function
|
|
.globl __riscv_restore_4
|
|
.type __riscv_restore_4,@function
|
|
__riscv_restore_7:
|
|
__riscv_restore_6:
|
|
__riscv_restore_5:
|
|
__riscv_restore_4:
|
|
lw s6, 0(sp)
|
|
lw s5, 4(sp)
|
|
lw s4, 8(sp)
|
|
lw s3, 12(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_3/2/1/0
|
|
|
|
.globl __riscv_restore_3
|
|
.type __riscv_restore_3,@function
|
|
.globl __riscv_restore_2
|
|
.type __riscv_restore_2,@function
|
|
.globl __riscv_restore_1
|
|
.type __riscv_restore_1,@function
|
|
.globl __riscv_restore_0
|
|
.type __riscv_restore_0,@function
|
|
__riscv_restore_3:
|
|
__riscv_restore_2:
|
|
__riscv_restore_1:
|
|
__riscv_restore_0:
|
|
lw s2, 0(sp)
|
|
lw s1, 4(sp)
|
|
lw s0, 8(sp)
|
|
lw ra, 12(sp)
|
|
addi sp, sp, 16
|
|
ret
|
|
|
|
#else
|
|
|
|
.globl __riscv_restore_2
|
|
.type __riscv_restore_2,@function
|
|
__riscv_restore_2:
|
|
lw s1, 0(sp)
|
|
addi sp, sp, 4
|
|
// fallthrough into __riscv_restore_1/0
|
|
|
|
.globl __riscv_restore_1
|
|
.type __riscv_restore_1,@function
|
|
__riscv_restore_1:
|
|
lw s0, 0(sp)
|
|
addi sp, sp, 4
|
|
// fallthrough into __riscv_restore_0
|
|
|
|
.globl __riscv_restore_0
|
|
.type __riscv_restore_0,@function
|
|
__riscv_restore_0:
|
|
lw ra, 0(sp)
|
|
addi sp, sp, 4
|
|
ret
|
|
|
|
#endif
|
|
|
|
#elif __riscv_xlen == 64
|
|
|
|
#ifndef __riscv_abi_rve
|
|
|
|
.globl __riscv_restore_12
|
|
.type __riscv_restore_12,@function
|
|
__riscv_restore_12:
|
|
ld s11, 8(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_11/10
|
|
|
|
.globl __riscv_restore_11
|
|
.type __riscv_restore_11,@function
|
|
.globl __riscv_restore_10
|
|
.type __riscv_restore_10,@function
|
|
__riscv_restore_11:
|
|
__riscv_restore_10:
|
|
ld s10, 0(sp)
|
|
ld s9, 8(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_9/8
|
|
|
|
.globl __riscv_restore_9
|
|
.type __riscv_restore_9,@function
|
|
.globl __riscv_restore_8
|
|
.type __riscv_restore_8,@function
|
|
__riscv_restore_9:
|
|
__riscv_restore_8:
|
|
ld s8, 0(sp)
|
|
ld s7, 8(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_7/6
|
|
|
|
.globl __riscv_restore_7
|
|
.type __riscv_restore_7,@function
|
|
.globl __riscv_restore_6
|
|
.type __riscv_restore_6,@function
|
|
__riscv_restore_7:
|
|
__riscv_restore_6:
|
|
ld s6, 0(sp)
|
|
ld s5, 8(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_5/4
|
|
|
|
.globl __riscv_restore_5
|
|
.type __riscv_restore_5,@function
|
|
.globl __riscv_restore_4
|
|
.type __riscv_restore_4,@function
|
|
__riscv_restore_5:
|
|
__riscv_restore_4:
|
|
ld s4, 0(sp)
|
|
ld s3, 8(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_3/2
|
|
|
|
.globl __riscv_restore_3
|
|
.type __riscv_restore_3,@function
|
|
.globl __riscv_restore_2
|
|
.type __riscv_restore_2,@function
|
|
__riscv_restore_3:
|
|
__riscv_restore_2:
|
|
ld s2, 0(sp)
|
|
ld s1, 8(sp)
|
|
addi sp, sp, 16
|
|
// fallthrough into __riscv_restore_1/0
|
|
|
|
.globl __riscv_restore_1
|
|
.type __riscv_restore_1,@function
|
|
.globl __riscv_restore_0
|
|
.type __riscv_restore_0,@function
|
|
__riscv_restore_1:
|
|
__riscv_restore_0:
|
|
ld s0, 0(sp)
|
|
ld ra, 8(sp)
|
|
addi sp, sp, 16
|
|
ret
|
|
|
|
#else
|
|
|
|
.globl __riscv_restore_2
|
|
.type __riscv_restore_2,@function
|
|
__riscv_restore_2:
|
|
ld s1, 0(sp)
|
|
addi sp, sp, 8
|
|
// fallthrough into __riscv_restore_1/0
|
|
|
|
.globl __riscv_restore_1
|
|
.type __riscv_restore_1,@function
|
|
__riscv_restore_1:
|
|
ld s0, 0(sp)
|
|
addi sp, sp, 8
|
|
// fallthrough into __riscv_restore_0
|
|
|
|
.globl __riscv_restore_0
|
|
.type __riscv_restore_0,@function
|
|
__riscv_restore_0:
|
|
ld ra, 0(sp)
|
|
addi sp, sp, 8
|
|
ret
|
|
|
|
#endif
|
|
|
|
#else
|
|
# error "xlen must be 32 or 64 for save-restore implementation
|
|
#endif
|