arm/libgcc: Support signed 64-bit division

Add support for signed 64-bit division. The implementation mostly
relies on __aeabi_uldivmod, which is already implemented.

ldivmod.S was adapted from CrOS EC version of ldivmod.S:
https://chromium.googlesource.com/chromiumos/platform/ec/+/main/third_party/libaeabi-cortexm0/core/cortex-m0/ldivmod.S

The CrOS EC version was adapted from:
https://github.com/bobbl/libaeabi-cortexm0/blob/master/ldivmod.S

BUG=b:240316722
BRANCH=None
TEST=Signed division works in PSP verstage (runs on ARM)

Change-Id: I53785c732b0fa35a4809bc054f1482c5461ada7b
Signed-off-by: Rob Barnes <robbarnes@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/66207
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Tim Van Patten <timvp@google.com>
This commit is contained in:
Rob Barnes 2022-07-27 18:57:07 +00:00 committed by Martin L Roth
parent b11f9f7e16
commit f6bb293f1c
3 changed files with 76 additions and 1 deletions

View File

@ -108,6 +108,7 @@ Jonas 'Sortie' Termansen
Jonathan A. Kollasch Jonathan A. Kollasch
Jonathan Neuschäfer Jonathan Neuschäfer
Jordan Crouse Jordan Crouse
Jörg Mische
Joseph Smith Joseph Smith
Keith Hui Keith Hui
Keith Packard Keith Packard

View File

@ -1,6 +1,6 @@
## SPDX-License-Identifier: GPL-2.0-only ## SPDX-License-Identifier: GPL-2.0-only
libgcc_files = ashldi3.S lib1funcs.S lshrdi3.S muldi3.S ucmpdi2.S uldivmod.S libgcc_files = ashldi3.S lib1funcs.S lshrdi3.S muldi3.S ucmpdi2.S uldivmod.S ldivmod.S
libgcc_files += udivmoddi4.c umoddi3.c libgcc_files += udivmoddi4.c umoddi3.c
ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM),y) ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM),y)

View File

@ -0,0 +1,74 @@
/* SPDX-License-Identifier: ISC OR GPL-2.0-only */
/*
* ldivmod.S: signed 64 bit division (quotient and remainder)
*
* Taken from CrOS EC: third_party/libaeabi-cortexm0/core/cortex-m0/ldivmod.S
*/
#include <arch/asm.h>
@ {long long quotient, long long remainder}
@ __aeabi_ldivmod(long long numerator, long long denominator)
@
@ Divide r1:r0 by r3:r2 and return the quotient in r1:r0 and the remainder in
@ r3:r2 (all signed)
@
ENTRY(__aeabi_ldivmod)
cmp r1, #0
bge L_num_pos
push {r4, lr}
movs r4, #0 @ num = -num
rsbs r0, r0, #0
sbcs r4, r1
mov r1, r4
cmp r3, #0
bge L_neg_both
movs r4, #0 @ den = -den
rsbs r2, r2, #0
sbcs r4, r3
mov r3, r4
bl __aeabi_uldivmod
movs r4, #0 @ rem = -rem
rsbs r2, r2, #0
sbcs r4, r3
mov r3, r4
pop {r4, pc}
L_neg_both:
bl __aeabi_uldivmod
movs r4, #0 @ quot = -quot
rsbs r0, r0, #0
sbcs r4, r1
mov r1, r4
movs r4, #0 @ rem = -rem
rsbs r2, r2, #0
sbcs r4, r3
mov r3, r4
pop {r4, pc}
L_num_pos:
cmp r3, #0
blt L_den_neg
push {r4, lr}
bl __aeabi_uldivmod @ offset too big for b / bge
pop {r4, pc}
L_den_neg:
push {r4, lr}
movs r4, #0 @ den = -den
rsbs r2, r2, #0
sbcs r4, r3
mov r3, r4
bl __aeabi_uldivmod
movs r4, #0 @ quot = -quot
rsbs r0, r0, #0
sbcs r4, r1
mov r1, r4
pop {r4, pc}