diff options
Diffstat (limited to 'src/arch/arm32/core')
| -rw-r--r-- | src/arch/arm32/core/arm32_bigint.c | 106 | ||||
| -rw-r--r-- | src/arch/arm32/core/pmccntr.S | 85 |
2 files changed, 85 insertions, 106 deletions
diff --git a/src/arch/arm32/core/arm32_bigint.c b/src/arch/arm32/core/arm32_bigint.c deleted file mode 100644 index 29fb40a7c..000000000 --- a/src/arch/arm32/core/arm32_bigint.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 multiplicand_size Number of elements in multiplicand - * @v multiplier0 Element 0 of big integer to be multiplied - * @v multiplier_size Number of elements in multiplier - * @v result0 Element 0 of big integer to hold result - */ -void bigint_multiply_raw ( const uint32_t *multiplicand0, - unsigned int multiplicand_size, - const uint32_t *multiplier0, - unsigned int multiplier_size, - uint32_t *result0 ) { - unsigned int result_size = ( multiplicand_size + multiplier_size ); - const bigint_t ( multiplicand_size ) __attribute__ (( may_alias )) - *multiplicand = ( ( const void * ) multiplicand0 ); - const bigint_t ( multiplier_size ) __attribute__ (( may_alias )) - *multiplier = ( ( const void * ) multiplier0 ); - bigint_t ( result_size ) __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 < multiplicand_size ; i++ ) { - multiplicand_element = multiplicand->element[i]; - for ( j = 0 ; j < multiplier_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^{m} => ab < 2^{n+m} - */ - __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/pmccntr.S b/src/arch/arm32/core/pmccntr.S new file mode 100644 index 000000000..c2fbeff4f --- /dev/null +++ b/src/arch/arm32/core/pmccntr.S @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2024 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 ) + +/** @file + * + * Performance Monitor Cycle Counter (PMCCNTR) + * + */ + + .section ".note.GNU-stack", "", %progbits + .text + .arm + +/* + * PMCCNTR status + * + * bit 31 set if PMCCNTR availability is not yet determined + * bit 0 set if PMCCNTR is available + * + */ + .section ".data.pmccntr_status", "aw", %progbits + .globl pmccntr_status +pmccntr_status: + .word 0x80000000 + +/* + * Check PMCCNTR availability + * + * Must preserve all registers, and return with either PMCCNTR enabled + * or the Z flag set to indicate unavailability. + * + */ + .section ".text.pmccntr_check", "ax", %progbits + .globl pmccntr_check + .type pmccntr_check, %function +pmccntr_check: + /* Save registers */ + stmfd sp!, { r0, r1 } + /* Read CPSR.M (bits 3:0, always permitted in PL0) */ + mrs r0, cpsr + and r0, r0, #0x0000000f + /* Read PMUSERENR.EN (bit 0, always permitted in PL0) */ + mrc p15, 0, r1, c9, c14, 0 + and r1, r1, #0x00000001 + /* Check if we are in PL1+ or in PL0 with PMUSERENR.EN set */ + orrs r0, r0, r1 + /* If PMCCNTR is unavailable, exit with status=0 and ZF set */ + beq 1f + /* Set PMCR.E (bit 0), set exit status=1 and ZF clear */ + movs r0, #0x00000001 + mcr p15, 0, r0, c9, c12, 0 + /* Set PMCNTENSET.C (bit 31) */ + mov r1, #0x80000000 + mcr p15, 0, r1, c9, c12, 1 +1: /* Store PMCCNTR status */ + ldr r1, pmccntr_status_ptr + str r0, [r1] + /* Restore registers and return */ + ldmfd sp!, { r0, r1 } + bx lr +pmccntr_status_ptr: + .word pmccntr_status + .size pmccntr_check, . - pmccntr_check |
