diff --git a/gnu-efi/inc/arm/efibind.h b/gnu-efi/inc/arm/efibind.h new file mode 100644 index 0000000..40a5a9c --- /dev/null +++ b/gnu-efi/inc/arm/efibind.h @@ -0,0 +1,164 @@ +/* + * Copright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long long uint64_t; +typedef long long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; // unqualified 'char' is unsigned on ARM + +#else +#include +#endif + +/* + * This prevents GCC from emitting GOT based relocations, and use R_ARM_REL32 + * relative relocations instead, which are more suitable for static binaries. + */ +#ifdef __GNUC__ +#pragma GCC visibility push (hidden) +#endif + +// +// Basic EFI types of various widths +// + +#ifndef __WCHAR_TYPE__ +# define __WCHAR_TYPE__ short +#endif + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef __WCHAR_TYPE__ WCHAR; + +#undef VOID +#define VOID void + +typedef int32_t INTN; +typedef uint32_t UINTN; + +#define EFIERR(a) (0x80000000 | a) +#define EFI_ERROR_MASK 0x80000000 +#define EFIERR_OEM(a) (0xc0000000 | a) + +#define BAD_POINTER 0xFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFF + +#define BREAKPOINT() while (TRUE); + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 4 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID *ImageHandle, \ + VOID *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE *systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. + +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/gnu-efi/inc/arm/efilibplat.h b/gnu-efi/inc/arm/efilibplat.h new file mode 100644 index 0000000..70a0786 --- /dev/null +++ b/gnu-efi/inc/arm/efilibplat.h @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + diff --git a/gnu-efi/inc/arm/efisetjmp_arch.h b/gnu-efi/inc/arm/efisetjmp_arch.h new file mode 100644 index 0000000..3a09ea5 --- /dev/null +++ b/gnu-efi/inc/arm/efisetjmp_arch.h @@ -0,0 +1,21 @@ +#ifndef GNU_EFI_ARM_SETJMP_H +#define GNU_EFI_ARM_SETJMP_H + +#define JMPBUF_ALIGN 4 + +typedef struct { + UINT32 R3; // A copy of R13 + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 R13; + UINT32 R14; +} ALIGN(JMPBUF_ALIGN) jmp_buf; + +#endif /* GNU_EFI_ARM_SETJMP_H */ diff --git a/gnu-efi/lib/arm/div.S b/gnu-efi/lib/arm/div.S new file mode 100644 index 0000000..71158b6 --- /dev/null +++ b/gnu-efi/lib/arm/div.S @@ -0,0 +1,155 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2011, ARM. All rights reserved.
+# +# 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. +# +#------------------------------------------------------------------------------ + +#include "edk2asm.h" + +.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 diff --git a/gnu-efi/lib/arm/edk2asm.h b/gnu-efi/lib/arm/edk2asm.h new file mode 100644 index 0000000..9515eaf --- /dev/null +++ b/gnu-efi/lib/arm/edk2asm.h @@ -0,0 +1,6 @@ + +#define ASM_PFX(x) x +#define GCC_ASM_EXPORT(x) \ + .globl x ; \ + .type x, %function + diff --git a/gnu-efi/lib/arm/efi_stub.S b/gnu-efi/lib/arm/efi_stub.S new file mode 100644 index 0000000..464eae5 --- /dev/null +++ b/gnu-efi/lib/arm/efi_stub.S @@ -0,0 +1 @@ +/* This stub is a stub to make the build happy */ diff --git a/gnu-efi/lib/arm/initplat.c b/gnu-efi/lib/arm/initplat.c new file mode 100644 index 0000000..135a649 --- /dev/null +++ b/gnu-efi/lib/arm/initplat.c @@ -0,0 +1,34 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#include "lib.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ +} + +#ifdef __GNUC__ +void __div0(void) +{ + // TODO handle divide by zero fault + while (1); +} +#endif diff --git a/gnu-efi/lib/arm/ldivmod.S b/gnu-efi/lib/arm/ldivmod.S new file mode 100644 index 0000000..edbf89e --- /dev/null +++ b/gnu-efi/lib/arm/ldivmod.S @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// 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. +// +//------------------------------------------------------------------------------ + + +#include "edk2asm.h" + + .text + .align 2 + GCC_ASM_EXPORT(__aeabi_ldivmod) + +// +// A pair of (unsigned) long longs is returned in {{r0, r1}, {r2, r3}}, +// the quotient in {r0, r1}, and the remainder in {r2, r3}. +// +//__value_in_regs lldiv_t +//EFIAPI +//__aeabi_ldivmod ( +// IN UINT64 Dividen +// IN UINT64 Divisor +// )// +// + +ASM_PFX(__aeabi_ldivmod): + push {r4,lr} + asrs r4,r1,#1 + eor r4,r4,r3,LSR #1 + bpl L_Test1 + rsbs r0,r0,#0 + rsc r1,r1,#0 +L_Test1: + tst r3,r3 + bpl L_Test2 + rsbs r2,r2,#0 + rsc r3,r3,#0 +L_Test2: + bl ASM_PFX(__aeabi_uldivmod) + tst r4,#0x40000000 + beq L_Test3 + rsbs r0,r0,#0 + rsc r1,r1,#0 +L_Test3: + tst r4,#0x80000000 + beq L_Exit + rsbs r2,r2,#0 + rsc r3,r3,#0 +L_Exit: + pop {r4,pc} + + + diff --git a/gnu-efi/lib/arm/llsl.S b/gnu-efi/lib/arm/llsl.S new file mode 100644 index 0000000..0f5c407 --- /dev/null +++ b/gnu-efi/lib/arm/llsl.S @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2013, ARM. All rights reserved.
+# +# 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. +# +#------------------------------------------------------------------------------ + +#include "edk2asm.h" + +.text +.align 2 +GCC_ASM_EXPORT(__aeabi_llsl) + +# +#VOID +#EFIAPI +#__aeabi_llsl ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINT32 Size +# ); +# +ASM_PFX(__aeabi_llsl): + subs r3,r2,#0x20 + bpl 1f + rsb r3,r2,#0x20 + lsl r1,r1,r2 + orr r1,r1,r0,lsr r3 + lsl r0,r0,r2 + bx lr +1: + lsl r1,r0,r3 + mov r0,#0 + bx lr diff --git a/gnu-efi/lib/arm/llsr.S b/gnu-efi/lib/arm/llsr.S new file mode 100644 index 0000000..432b27d --- /dev/null +++ b/gnu-efi/lib/arm/llsr.S @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2013, ARM. All rights reserved.
+# +# 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. +# +#------------------------------------------------------------------------------ + +#include "edk2asm.h" + +.text +.align 2 +GCC_ASM_EXPORT(__aeabi_llsr) + +# +#VOID +#EFIAPI +#__aeabi_llsr ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINT32 Size +# ); +# +ASM_PFX(__aeabi_llsr): + subs r3,r2,#0x20 + bpl 1f + rsb r3,r2,#0x20 + lsr r0,r0,r2 + orr r0,r0,r1,lsl r3 + lsr r1,r1,r2 + bx lr +1: + lsr r0,r1,r3 + mov r1,#0 + bx lr diff --git a/gnu-efi/lib/arm/math.c b/gnu-efi/lib/arm/math.c new file mode 100644 index 0000000..4793ae2 --- /dev/null +++ b/gnu-efi/lib/arm/math.c @@ -0,0 +1,67 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#include "lib.h" + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Left shift 64bit by 32bit and get a 64bit result +{ + return Operand << Count; +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Right shift 64bit by 32bit and get a 64bit result +{ + return Operand >> Count; +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +// Multiply 64bit by 32bit and get a 64bit result +{ + return Multiplicand * Multiplier; +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +{ + /* + * GCC turns a division into a multiplication and shift with precalculated + * constants if the divisor is constant and the dividend fits into a 32 bit + * variable. Otherwise, it will turn this into calls into the 32-bit div + * library functions. + */ + if (Remainder) + *Remainder = Dividend % Divisor; + return Dividend / Divisor; +} diff --git a/gnu-efi/lib/arm/mullu.S b/gnu-efi/lib/arm/mullu.S new file mode 100644 index 0000000..39b9a80 --- /dev/null +++ b/gnu-efi/lib/arm/mullu.S @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# +# 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. +# +#------------------------------------------------------------------------------ + +#include "edk2asm.h" + +.text +GCC_ASM_EXPORT(__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} diff --git a/gnu-efi/lib/arm/setjmp.S b/gnu-efi/lib/arm/setjmp.S new file mode 100644 index 0000000..bd61a8d --- /dev/null +++ b/gnu-efi/lib/arm/setjmp.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * 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 + .arm + .globl setjmp + .type setjmp, %function +setjmp: + mov r3, r13 + stmia r0, {r3-r12,r14} + eor r0, r0, r0 + bx lr + + .globl longjmp + .type longjmp, %function +longjmp: + ldmia r0, {r3-r12,r14} diff --git a/gnu-efi/lib/arm/uldiv.S b/gnu-efi/lib/arm/uldiv.S new file mode 100644 index 0000000..f478898 --- /dev/null +++ b/gnu-efi/lib/arm/uldiv.S @@ -0,0 +1,267 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// 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. +// +//------------------------------------------------------------------------------ + +#include "edk2asm.h" + + .text + .align 2 + GCC_ASM_EXPORT(__aeabi_uldivmod) + +// +//UINT64 +//EFIAPI +//__aeabi_uldivmod ( +// IN UINT64 Dividend +// IN UINT64 Divisor +// ) +// +ASM_PFX(__aeabi_uldivmod): + stmdb sp!, {r4, r5, r6, lr} + mov r4, r1 + mov r5, r0 + mov r6, #0 // 0x0 + orrs ip, r3, r2, lsr #31 + bne ASM_PFX(__aeabi_uldivmod_label1) + tst r2, r2 + beq ASM_PFX(_ll_div0) + movs ip, r2, lsr #15 + addeq r6, r6, #16 // 0x10 + mov ip, r2, lsl r6 + movs lr, ip, lsr #23 + moveq ip, ip, lsl #8 + addeq r6, r6, #8 // 0x8 + movs lr, ip, lsr #27 + moveq ip, ip, lsl #4 + addeq r6, r6, #4 // 0x4 + movs lr, ip, lsr #29 + moveq ip, ip, lsl #2 + addeq r6, r6, #2 // 0x2 + movs lr, ip, lsr #30 + moveq ip, ip, lsl #1 + addeq r6, r6, #1 // 0x1 + b ASM_PFX(_ll_udiv_small) +ASM_PFX(__aeabi_uldivmod_label1): + tst r3, #-2147483648 // 0x80000000 + bne ASM_PFX(__aeabi_uldivmod_label2) + movs ip, r3, lsr #15 + addeq r6, r6, #16 // 0x10 + mov ip, r3, lsl r6 + movs lr, ip, lsr #23 + moveq ip, ip, lsl #8 + addeq r6, r6, #8 // 0x8 + movs lr, ip, lsr #27 + moveq ip, ip, lsl #4 + addeq r6, r6, #4 // 0x4 + movs lr, ip, lsr #29 + moveq ip, ip, lsl #2 + addeq r6, r6, #2 // 0x2 + movs lr, ip, lsr #30 + addeq r6, r6, #1 // 0x1 + rsb r3, r6, #32 // 0x20 + moveq ip, ip, lsl #1 + orr ip, ip, r2, lsr r3 + mov lr, r2, lsl r6 + b ASM_PFX(_ll_udiv_big) +ASM_PFX(__aeabi_uldivmod_label2): + mov ip, r3 + mov lr, r2 + b ASM_PFX(_ll_udiv_ginormous) + +ASM_PFX(_ll_udiv_small): + cmp r4, ip, lsl #1 + mov r3, #0 // 0x0 + subcs r4, r4, ip, lsl #1 + addcs r3, r3, #2 // 0x2 + cmp r4, ip + subcs r4, r4, ip + adcs r3, r3, #0 // 0x0 + add r2, r6, #32 // 0x20 + cmp r2, #32 // 0x20 + rsb ip, ip, #0 // 0x0 + bcc ASM_PFX(_ll_udiv_small_label1) + orrs r0, r4, r5, lsr #30 + moveq r4, r5 + moveq r5, #0 // 0x0 + subeq r2, r2, #32 // 0x20 +ASM_PFX(_ll_udiv_small_label1): + mov r1, #0 // 0x0 + cmp r2, #16 // 0x10 + bcc ASM_PFX(_ll_udiv_small_label2) + movs r0, r4, lsr #14 + moveq r4, r4, lsl #16 + addeq r1, r1, #16 // 0x10 +ASM_PFX(_ll_udiv_small_label2): + sub lr, r2, r1 + cmp lr, #8 // 0x8 + bcc ASM_PFX(_ll_udiv_small_label3) + movs r0, r4, lsr #22 + moveq r4, r4, lsl #8 + addeq r1, r1, #8 // 0x8 +ASM_PFX(_ll_udiv_small_label3): + rsb r0, r1, #32 // 0x20 + sub r2, r2, r1 + orr r4, r4, r5, lsr r0 + mov r5, r5, lsl r1 + cmp r2, #1 // 0x1 + bcc ASM_PFX(_ll_udiv_small_label5) + sub r2, r2, #1 // 0x1 + and r0, r2, #7 // 0x7 + eor r0, r0, #7 // 0x7 + adds r0, r0, r0, lsl #1 + add pc, pc, r0, lsl #2 + nop // (mov r0,r0) +ASM_PFX(_ll_udiv_small_label4): + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + sub r2, r2, #8 // 0x8 + tst r2, r2 + rsbcc r4, ip, r4 + bpl ASM_PFX(_ll_udiv_small_label4) +ASM_PFX(_ll_udiv_small_label5): + mov r2, r4, lsr r6 + bic r4, r4, r2, lsl r6 + adcs r0, r5, r5 + adc r1, r4, r4 + add r1, r1, r3, lsl r6 + mov r3, #0 // 0x0 + ldmia sp!, {r4, r5, r6, pc} + +ASM_PFX(_ll_udiv_big): + subs r0, r5, lr + mov r3, #0 // 0x0 + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 // 0x0 + subs r0, r5, lr + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 // 0x0 + subs r0, r5, lr + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 // 0x0 + mov r1, #0 // 0x0 + rsbs lr, lr, #0 // 0x0 + rsc ip, ip, #0 // 0x0 + cmp r6, #16 // 0x10 + bcc ASM_PFX(_ll_udiv_big_label1) + movs r0, r4, lsr #14 + moveq r4, r4, lsl #16 + addeq r1, r1, #16 // 0x10 +ASM_PFX(_ll_udiv_big_label1): + sub r2, r6, r1 + cmp r2, #8 // 0x8 + bcc ASM_PFX(_ll_udiv_big_label2) + movs r0, r4, lsr #22 + moveq r4, r4, lsl #8 + addeq r1, r1, #8 // 0x8 +ASM_PFX(_ll_udiv_big_label2): + rsb r0, r1, #32 // 0x20 + sub r2, r6, r1 + orr r4, r4, r5, lsr r0 + mov r5, r5, lsl r1 + cmp r2, #1 // 0x1 + bcc ASM_PFX(_ll_udiv_big_label4) + sub r2, r2, #1 // 0x1 + and r0, r2, #3 // 0x3 + rsb r0, r0, #3 // 0x3 + adds r0, r0, r0, lsl #1 + add pc, pc, r0, lsl #3 + nop // (mov r0,r0) +ASM_PFX(_ll_udiv_big_label3): + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + sub r2, r2, #4 // 0x4 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + tst r2, r2 + movcs r5, r0 + movcs r4, r1 + bpl ASM_PFX(_ll_udiv_big_label3) +ASM_PFX(_ll_udiv_big_label4): + mov r1, #0 // 0x0 + mov r2, r5, lsr r6 + bic r5, r5, r2, lsl r6 + adcs r0, r5, r5 + adc r1, r1, #0 // 0x0 + movs lr, r3, lsl r6 + mov r3, r4, lsr r6 + bic r4, r4, r3, lsl r6 + adc r1, r1, #0 // 0x0 + adds r0, r0, lr + orr r2, r2, r4, ror r6 + adc r1, r1, #0 // 0x0 + ldmia sp!, {r4, r5, r6, pc} + +ASM_PFX(_ll_udiv_ginormous): + subs r2, r5, lr + mov r1, #0 // 0x0 + sbcs r3, r4, ip + adc r0, r1, r1 + movcc r2, r5 + movcc r3, r4 + ldmia sp!, {r4, r5, r6, pc} + +ASM_PFX(_ll_div0): + ldmia sp!, {r4, r5, r6, lr} + mov r0, #0 // 0x0 + mov r1, #0 // 0x0 + b ASM_PFX(__aeabi_ldiv0) + +ASM_PFX(__aeabi_ldiv0): + bx r14 + +