diff options
| author | Simon Rettberg | 2026-01-28 12:53:53 +0100 |
|---|---|---|
| committer | Simon Rettberg | 2026-01-28 12:53:53 +0100 |
| commit | 8e82785c584dc13e20f9229decb95bd17bbe9cd1 (patch) | |
| tree | a8b359e59196be5b2e3862bed189107f4bc9975f /src/arch/arm32/include/bits/bigint.h | |
| parent | Merge branch 'master' into openslx (diff) | |
| parent | [prefix] Make unlzma.S compatible with 386 class CPUs (diff) | |
| download | ipxe-openslx.tar.gz ipxe-openslx.tar.xz ipxe-openslx.zip | |
Merge branch 'master' into openslxopenslx
Diffstat (limited to 'src/arch/arm32/include/bits/bigint.h')
| -rw-r--r-- | src/arch/arm32/include/bits/bigint.h | 107 |
1 files changed, 63 insertions, 44 deletions
diff --git a/src/arch/arm32/include/bits/bigint.h b/src/arch/arm32/include/bits/bigint.h index e4b511da7..988bef5ff 100644 --- a/src/arch/arm32/include/bits/bigint.h +++ b/src/arch/arm32/include/bits/bigint.h @@ -43,8 +43,9 @@ bigint_init_raw ( uint32_t *value0, unsigned int size, * @v addend0 Element 0 of big integer to add * @v value0 Element 0 of big integer to be added to * @v size Number of elements + * @ret carry Carry out */ -static inline __attribute__ (( always_inline )) void +static inline __attribute__ (( always_inline )) int bigint_add_raw ( const uint32_t *addend0, uint32_t *value0, unsigned int size ) { bigint_t ( size ) __attribute__ (( may_alias )) *value = @@ -54,8 +55,9 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0, uint32_t *discard_end; uint32_t discard_addend_i; uint32_t discard_value_i; + int carry; - __asm__ __volatile__ ( "adds %2, %0, %8, lsl #2\n\t" /* clear CF */ + __asm__ __volatile__ ( "adds %2, %0, %9, lsl #2\n\t" /* clear CF */ "\n1:\n\t" "ldmia %0!, {%3}\n\t" "ldr %4, [%1]\n\t" @@ -68,9 +70,11 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0, "=l" ( discard_end ), "=l" ( discard_addend_i ), "=l" ( discard_value_i ), + "=@cccs" ( carry ), "+m" ( *value ) - : "0" ( addend0 ), "1" ( value0 ), "l" ( size ) - : "cc" ); + : "0" ( addend0 ), "1" ( value0 ), + "l" ( size ) ); + return carry; } /** @@ -79,8 +83,9 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0, * @v subtrahend0 Element 0 of big integer to subtract * @v value0 Element 0 of big integer to be subtracted from * @v size Number of elements + * @ret borrow Borrow out */ -static inline __attribute__ (( always_inline )) void +static inline __attribute__ (( always_inline )) int bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0, unsigned int size ) { bigint_t ( size ) __attribute__ (( may_alias )) *value = @@ -90,8 +95,9 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0, uint32_t *discard_end; uint32_t discard_subtrahend_i; uint32_t discard_value_i; + int borrow; - __asm__ __volatile__ ( "add %2, %0, %8, lsl #2\n\t" + __asm__ __volatile__ ( "add %2, %0, %9, lsl #2\n\t" "cmp %2, %0\n\t" /* set CF */ "\n1:\n\t" "ldmia %0!, {%3}\n\t" @@ -105,27 +111,30 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0, "=l" ( discard_end ), "=l" ( discard_subtrahend_i ), "=l" ( discard_value_i ), + "=@cccc" ( borrow ), "+m" ( *value ) : "0" ( subtrahend0 ), "1" ( value0 ), - "l" ( size ) - : "cc" ); + "l" ( size ) ); + return borrow; } /** - * Rotate big integer left + * Shift big integer left * * @v value0 Element 0 of big integer * @v size Number of elements + * @ret out Bit shifted out */ -static inline __attribute__ (( always_inline )) void -bigint_rol_raw ( uint32_t *value0, unsigned int size ) { +static inline __attribute__ (( always_inline )) int +bigint_shl_raw ( uint32_t *value0, unsigned int size ) { bigint_t ( size ) __attribute__ (( may_alias )) *value = ( ( void * ) value0 ); uint32_t *discard_value; uint32_t *discard_end; uint32_t discard_value_i; + int carry; - __asm__ __volatile__ ( "adds %1, %0, %5, lsl #2\n\t" /* clear CF */ + __asm__ __volatile__ ( "adds %1, %0, %1, lsl #2\n\t" /* clear CF */ "\n1:\n\t" "ldr %2, [%0]\n\t" "adcs %2, %2\n\t" @@ -135,26 +144,29 @@ bigint_rol_raw ( uint32_t *value0, unsigned int size ) { : "=l" ( discard_value ), "=l" ( discard_end ), "=l" ( discard_value_i ), + "=@cccs" ( carry ), "+m" ( *value ) - : "0" ( value0 ), "1" ( size ) - : "cc" ); + : "0" ( value0 ), "1" ( size ) ); + return carry; } /** - * Rotate big integer right + * Shift big integer right * * @v value0 Element 0 of big integer * @v size Number of elements + * @ret out Bit shifted out */ -static inline __attribute__ (( always_inline )) void -bigint_ror_raw ( uint32_t *value0, unsigned int size ) { +static inline __attribute__ (( always_inline )) int +bigint_shr_raw ( uint32_t *value0, unsigned int size ) { bigint_t ( size ) __attribute__ (( may_alias )) *value = ( ( void * ) value0 ); uint32_t *discard_value; uint32_t *discard_end; uint32_t discard_value_i; + int carry; - __asm__ __volatile__ ( "adds %1, %0, %5, lsl #2\n\t" /* clear CF */ + __asm__ __volatile__ ( "adds %1, %0, %1, lsl #2\n\t" /* clear CF */ "\n1:\n\t" "ldmdb %1!, {%2}\n\t" "rrxs %2, %2\n\t" @@ -164,9 +176,10 @@ bigint_ror_raw ( uint32_t *value0, unsigned int size ) { : "=l" ( discard_value ), "=l" ( discard_end ), "=l" ( discard_value_i ), + "=@cccs" ( carry ), "+m" ( *value ) - : "0" ( value0 ), "1" ( size ) - : "cc" ); + : "0" ( value0 ), "1" ( size ) ); + return carry; } /** @@ -217,25 +230,6 @@ bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0, } /** - * Test if bit is set in big integer - * - * @v value0 Element 0 of big integer - * @v size Number of elements - * @v bit Bit to test - * @ret is_set Bit is set - */ -static inline __attribute__ (( always_inline )) int -bigint_bit_is_set_raw ( const uint32_t *value0, unsigned int size, - unsigned int bit ) { - const bigint_t ( size ) __attribute__ (( may_alias )) *value = - ( ( const void * ) value0 ); - unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) ); - unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) ); - - return ( value->element[index] & ( 1 << subindex ) ); -} - -/** * Find highest bit set in big integer * * @v value0 Element 0 of big integer @@ -309,10 +303,35 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused, *(--out_byte) = *(value_byte++); } -extern void bigint_multiply_raw ( const uint32_t *multiplicand0, - unsigned int multiplicand_size, - const uint32_t *multiplier0, - unsigned int multiplier_size, - uint32_t *value0 ); +/** + * Multiply big integer elements + * + * @v multiplicand Multiplicand element + * @v multiplier Multiplier element + * @v result Result element + * @v carry Carry element + */ +static inline __attribute__ (( always_inline )) void +bigint_multiply_one ( const uint32_t multiplicand, const uint32_t multiplier, + uint32_t *result, uint32_t *carry ) { + uint32_t discard_low; + uint32_t discard_high; + + __asm__ __volatile__ ( /* Perform multiplication */ + "umull %0, %1, %4, %5\n\t" + /* Accumulate result */ + "adds %2, %0\n\t" + "adc %1, #0\n\t" + /* Accumulate carry (cannot overflow) */ + "adds %2, %3\n\t" + "adc %3, %1, #0\n\t" + : "=r" ( discard_low ), + "=r" ( discard_high ), + "+r" ( *result ), + "+r" ( *carry ) + : "r" ( multiplicand ), + "r" ( multiplier ) + : "cc" ); +} #endif /* _BITS_BIGINT_H */ |
