diff options
| author | Michael Brown | 2016-05-08 01:18:35 +0200 |
|---|---|---|
| committer | Michael Brown | 2016-05-08 01:18:35 +0200 |
| commit | edea3a434ccae8dc980c715949287c9ba63babf5 (patch) | |
| tree | d821d987dcf1ac0bc4f22e1363fa32c95f6bd0b2 /src/arch/arm32/core | |
| parent | [arm] Avoid instruction references to symbols defined via ".equ" (diff) | |
| download | ipxe-edea3a434ccae8dc980c715949287c9ba63babf5.tar.gz ipxe-edea3a434ccae8dc980c715949287c9ba63babf5.tar.xz ipxe-edea3a434ccae8dc980c715949287c9ba63babf5.zip | |
[arm] Split out 32-bit-specific code to arch/arm32
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch/arm32/core')
| -rw-r--r-- | src/arch/arm32/core/arm32_bigint.c | 102 | ||||
| -rw-r--r-- | src/arch/arm32/core/setjmp.S | 32 |
2 files changed, 134 insertions, 0 deletions
diff --git a/src/arch/arm32/core/arm32_bigint.c b/src/arch/arm32/core/arm32_bigint.c new file mode 100644 index 000000000..839bead18 --- /dev/null +++ b/src/arch/arm32/core/arm32_bigint.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <stdint.h> +#include <string.h> +#include <ipxe/bigint.h> + +/** @file + * + * Big integer support + */ + +/** + * Multiply big integers + * + * @v multiplicand0 Element 0 of big integer to be multiplied + * @v multiplier0 Element 0 of big integer to be multiplied + * @v result0 Element 0 of big integer to hold result + * @v size Number of elements + */ +void bigint_multiply_raw ( const uint32_t *multiplicand0, + const uint32_t *multiplier0, + uint32_t *result0, unsigned int size ) { + const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand = + ( ( const void * ) multiplicand0 ); + const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier = + ( ( const void * ) multiplier0 ); + bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result = + ( ( void * ) result0 ); + unsigned int i; + unsigned int j; + uint32_t multiplicand_element; + uint32_t multiplier_element; + uint32_t *result_elements; + uint32_t discard_low; + uint32_t discard_high; + uint32_t discard_temp; + + /* Zero result */ + memset ( result, 0, sizeof ( *result ) ); + + /* Multiply integers one element at a time */ + for ( i = 0 ; i < size ; i++ ) { + multiplicand_element = multiplicand->element[i]; + for ( j = 0 ; j < size ; j++ ) { + multiplier_element = multiplier->element[j]; + result_elements = &result->element[ i + j ]; + /* Perform a single multiply, and add the + * resulting double-element into the result, + * carrying as necessary. The carry can + * never overflow beyond the end of the + * result, since: + * + * a < 2^{n}, b < 2^{n} => ab < 2^{2n} + */ + __asm__ __volatile__ ( "umull %1, %2, %5, %6\n\t" + "ldr %3, [%0]\n\t" + "adds %3, %1\n\t" + "stmia %0!, {%3}\n\t" + "ldr %3, [%0]\n\t" + "adcs %3, %2\n\t" + "stmia %0!, {%3}\n\t" + "bcc 2f\n\t" + "\n1:\n\t" + "ldr %3, [%0]\n\t" + "adcs %3, #0\n\t" + "stmia %0!, {%3}\n\t" + "bcs 1b\n\t" + "\n2:\n\t" + : "+l" ( result_elements ), + "=l" ( discard_low ), + "=l" ( discard_high ), + "=l" ( discard_temp ), + "+m" ( *result ) + : "l" ( multiplicand_element ), + "l" ( multiplier_element ) + : "cc" ); + } + } +} diff --git a/src/arch/arm32/core/setjmp.S b/src/arch/arm32/core/setjmp.S new file mode 100644 index 000000000..7e7b0fe58 --- /dev/null +++ b/src/arch/arm32/core/setjmp.S @@ -0,0 +1,32 @@ +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) + + .text + .arm + +/* + * Save stack context for non-local goto + */ + .globl setjmp + .type setjmp, %function +setjmp: + /* Store registers */ + stmia r0, { r4, r5, r6, r7, r8, r9, r10, fp, sp, lr } + /* Return 0 when returning as setjmp() */ + mov r0, #0 + bx lr + .size setjmp, . - setjmp + +/* + * Non-local jump to a saved stack context + */ + .globl longjmp + .type longjmp, %function +longjmp: + /* Restore registers */ + ldmia r0, { r4, r5, r6, r7, r8, r9, r10, fp, sp, lr } + /* Force result to non-zero */ + movs r0, r1 + moveq r0, #1 + /* Return to setjmp() caller */ + bx lr + .size longjmp, . - longjmp |
