diff options
-rw-r--r-- | ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.S | 156 | ||||
-rw-r--r-- | ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.S | 46 | ||||
-rw-r--r-- | ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf | 4 |
3 files changed, 205 insertions, 1 deletions
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.S new file mode 100644 index 0000000000..2f133665b5 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.S @@ -0,0 +1,156 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2011, ARM. All rights reserved.<BR> +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .align 2 + GCC_ASM_EXPORT(__aeabi_uidiv) + GCC_ASM_EXPORT(__aeabi_uidivmod) + GCC_ASM_EXPORT(__aeabi_idiv) + GCC_ASM_EXPORT(__aeabi_idivmod) + +# AREA Math, CODE, READONLY + +# +#UINT32 +#EFIAPI +#__aeabi_uidivmode ( +# IN UINT32 Dividen +# IN UINT32 Divisor +# ); +# + +ASM_PFX(__aeabi_uidiv): +ASM_PFX(__aeabi_uidivmod): + RSBS r12, r1, r0, LSR #4 + MOV r2, #0 + BCC ASM_PFX(__arm_div4) + RSBS r12, r1, r0, LSR #8 + BCC ASM_PFX(__arm_div8) + MOV r3, #0 + B ASM_PFX(__arm_div_large) + +# +#INT32 +#EFIAPI +#__aeabi_idivmode ( +# IN INT32 Dividen +# IN INT32 Divisor +# ); +# +ASM_PFX(__aeabi_idiv): +ASM_PFX(__aeabi_idivmod): + ORRS r12, r0, r1 + BMI ASM_PFX(__arm_div_negative) + RSBS r12, r1, r0, LSR #1 + MOV r2, #0 + BCC ASM_PFX(__arm_div1) + RSBS r12, r1, r0, LSR #4 + BCC ASM_PFX(__arm_div4) + RSBS r12, r1, r0, LSR #8 + BCC ASM_PFX(__arm_div8) + MOV r3, #0 + B ASM_PFX(__arm_div_large) +ASM_PFX(__arm_div8): + RSBS r12, r1, r0, LSR #7 + SUBCS r0, r0, r1, LSL #7 + ADC r2, r2, r2 + RSBS r12, r1, r0,LSR #6 + SUBCS r0, r0, r1, LSL #6 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #5 + SUBCS r0, r0, r1, LSL #5 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #4 + SUBCS r0, r0, r1, LSL #4 + ADC r2, r2, r2 +ASM_PFX(__arm_div4): + RSBS r12, r1, r0, LSR #3 + SUBCS r0, r0, r1, LSL #3 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #2 + SUBCS r0, r0, r1, LSL #2 + ADCS r2, r2, r2 + RSBS r12, r1, r0, LSR #1 + SUBCS r0, r0, r1, LSL #1 + ADC r2, r2, r2 +ASM_PFX(__arm_div1): + SUBS r1, r0, r1 + MOVCC r1, r0 + ADC r0, r2, r2 + BX r14 +ASM_PFX(__arm_div_negative): + ANDS r2, r1, #0x80000000 + RSBMI r1, r1, #0 + EORS r3, r2, r0, ASR #32 + RSBCS r0, r0, #0 + RSBS r12, r1, r0, LSR #4 + BCC label1 + RSBS r12, r1, r0, LSR #8 + BCC label2 +ASM_PFX(__arm_div_large): + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0xfc000000 + BCC label2 + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0x3f00000 + BCC label2 + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0xfc000 + ORRCS r2, r2, #0x3f00 + LSLCS r1, r1, #6 + RSBS r12, r1, #0 + BCS ASM_PFX(__aeabi_idiv0) +label3: + LSRCS r1, r1, #6 +label2: + RSBS r12, r1, r0, LSR #7 + SUBCS r0, r0, r1, LSL #7 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #6 + SUBCS r0, r0, r1, LSL #6 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #5 + SUBCS r0, r0, r1, LSL #5 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #4 + SUBCS r0, r0, r1, LSL #4 + ADC r2, r2, r2 +label1: + RSBS r12, r1, r0, LSR #3 + SUBCS r0, r0, r1, LSL #3 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #2 + SUBCS r0, r0, r1, LSL #2 + ADCS r2, r2, r2 + BCS label3 + RSBS r12, r1, r0, LSR #1 + SUBCS r0, r0, r1, LSL #1 + ADC r2, r2, r2 + SUBS r1, r0, r1 + MOVCC r1, r0 + ADC r0, r2, r2 + ASRS r3, r3, #31 + RSBMI r0, r0, #0 + RSBCS r1, r1, #0 + BX r14 + + @ What to do about division by zero? For now, just return. +ASM_PFX(__aeabi_idiv0): + BX r14 + +.end + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.S new file mode 100644 index 0000000000..e6d85db0a0 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#------------------------------------------------------------------------------
+.text
+
+GCC_ASM_EXPORT(__ARM_ll_mullu)
+GCC_ASM_EXPORT(__aeabi_lmul)
+#
+#INT64
+#EFIAPI
+#__aeabi_lmul (
+# IN INT64 Multiplicand
+# IN INT32 Multiplier
+# );
+#
+ASM_PFX(__ARM_ll_mullu):
+ mov r3, #0
+# Make upper part of INT64 Multiplier 0 and use __aeabi_lmul
+
+#
+#INT64
+#EFIAPI
+#__aeabi_lmul (
+# IN INT64 Multiplicand
+# IN INT64 Multiplier
+# );
+#
+ASM_PFX(__aeabi_lmul):
+ stmdb sp!, {lr}
+ mov lr, r0
+ umull r0, ip, r2, lr
+ mla r1, r2, r1, ip
+ mla r1, r3, lr, r1
+ ldmia sp!, {pc}
+
+.end
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf b/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf index a3d399939d..ef6f42a8b5 100644 --- a/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf +++ b/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf @@ -51,6 +51,7 @@ # Arm/lshrdi3.c | GCC Arm/ashrdi3.S | GCC Arm/ashldi3.S | GCC + Arm/div.S | GCC Arm/divdi3.S | GCC Arm/divsi3.S | GCC Arm/lshrdi3.S | GCC @@ -63,7 +64,8 @@ # Arm/muldi3.c | GCC Arm/modsi3.S | GCC Arm/moddi3.S | GCC - Arm/muldi3.S | GCC + Arm/muldi3.S | GCC + Arm/mullu.S | GCC # Arm/udivsi3.c | GCC # Arm/umodsi3.c | GCC |