diff options
Diffstat (limited to 'src/arch/loong64')
-rw-r--r-- | src/arch/loong64/core/loong64_bigint.c | 26 | ||||
-rw-r--r-- | src/arch/loong64/include/bits/bigint.h | 188 | ||||
-rw-r--r-- | src/arch/loong64/interface/efi/efiloong64_nap.c | 6 |
3 files changed, 129 insertions, 91 deletions
diff --git a/src/arch/loong64/core/loong64_bigint.c b/src/arch/loong64/core/loong64_bigint.c index f42b8611..b428e22c 100644 --- a/src/arch/loong64/core/loong64_bigint.c +++ b/src/arch/loong64/core/loong64_bigint.c @@ -37,19 +37,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * 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 - * @v size Number of elements */ void bigint_multiply_raw ( const uint64_t *multiplicand0, + unsigned int multiplicand_size, const uint64_t *multiplier0, - uint64_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 multiplier_size, + uint64_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; uint64_t multiplicand_element; @@ -64,9 +68,9 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0, memset ( result, 0, sizeof ( *result ) ); /* Multiply integers one element at a time */ - for ( i = 0 ; i < size ; i++ ) { + for ( i = 0 ; i < multiplicand_size ; i++ ) { multiplicand_element = multiplicand->element[i]; - for ( j = 0 ; j < size ; j++ ) { + 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 @@ -75,7 +79,7 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0, * never overflow beyond the end of the * result, since: * - * a < 2^{n}, b < 2^{n} => ab < 2^{2n} + * a < 2^{n}, b < 2^{m} => ab < 2^{n+m} */ __asm__ __volatile__ ( "mul.d %1, %6, %7\n\t" "mulh.du %2, %6, %7\n\t" diff --git a/src/arch/loong64/include/bits/bigint.h b/src/arch/loong64/include/bits/bigint.h index 89e0b867..bec748be 100644 --- a/src/arch/loong64/include/bits/bigint.h +++ b/src/arch/loong64/include/bits/bigint.h @@ -53,34 +53,37 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0, uint64_t *discard_value; uint64_t discard_addend_i; uint64_t discard_value_i; + uint64_t discard_carry; + uint64_t discard_temp; unsigned int discard_size; - __asm__ __volatile__ ( "move $t0, $zero\n" - "1:\n\t" - "ld.d %3, %0, 0\n\t" - "addi.d %0, %0, 8\n\t" - "ld.d %4, %1, 0\n\t" - - "add.d %4, %4, $t0\n\t" - "sltu $t0, %4, $t0\n\t" - - "add.d %4, %4, %3\n\t" - "sltu $t1, %4, %3\n\t" - "or $t0, $t0, $t1\n\t" - "st.d %4, %1, 0\n\t" + __asm__ __volatile__ ( "\n1:\n\t" + /* Load addend[i] and value[i] */ + "ld.d %3, %0, 0\n\t" + "ld.d %4, %1, 0\n\t" + /* Add carry flag and addend */ + "add.d %4, %4, %5\n\t" + "sltu %6, %4, %5\n\t" + "add.d %4, %4, %3\n\t" + "sltu %5, %4, %3\n\t" + "or %5, %5, %6\n\t" + /* Store value[i] */ + "st.d %4, %1, 0\n\t" + /* Loop */ + "addi.d %0, %0, 8\n\t" "addi.d %1, %1, 8\n\t" "addi.w %2, %2, -1\n\t" - "bnez %2, 1b" + "bnez %2, 1b\n\t" : "=r" ( discard_addend ), "=r" ( discard_value ), "=r" ( discard_size ), "=r" ( discard_addend_i ), "=r" ( discard_value_i ), + "=r" ( discard_carry ), + "=r" ( discard_temp ), "+m" ( *value ) - : "0" ( addend0 ), - "1" ( value0 ), - "2" ( size ) - : "t0", "t1" ); + : "0" ( addend0 ), "1" ( value0 ), + "2" ( size ), "5" ( 0 ) ); } /** @@ -93,35 +96,43 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0, static inline __attribute__ (( always_inline )) void bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0, unsigned int size ) { + bigint_t ( size ) __attribute__ (( may_alias )) *value = + ( ( void * ) value0 ); uint64_t *discard_subtrahend; uint64_t *discard_value; uint64_t discard_subtrahend_i; uint64_t discard_value_i; + uint64_t discard_carry; + uint64_t discard_temp; unsigned int discard_size; - unsigned int flag = 0; - - discard_subtrahend = (uint64_t*) subtrahend0; - discard_value = value0; - discard_size = size; - - do { - discard_subtrahend_i = *discard_subtrahend; - discard_subtrahend++; - discard_value_i = *discard_value; - - discard_value_i = discard_value_i - discard_subtrahend_i - flag; - - if ( *discard_value < (discard_subtrahend_i + flag)) { - flag = 1; - } else { - flag = 0; - } - *discard_value = discard_value_i; - - discard_value++; - discard_size -= 1; - } while (discard_size != 0); + __asm__ __volatile__ ( "\n1:\n\t" + /* Load subtrahend[i] and value[i] */ + "ld.d %3, %0, 0\n\t" + "ld.d %4, %1, 0\n\t" + /* Subtract carry flag and subtrahend */ + "sltu %6, %4, %5\n\t" + "sub.d %4, %4, %5\n\t" + "sltu %5, %4, %3\n\t" + "sub.d %4, %4, %3\n\t" + "or %5, %5, %6\n\t" + /* Store value[i] */ + "st.d %4, %1, 0\n\t" + /* Loop */ + "addi.d %0, %0, 8\n\t" + "addi.d %1, %1, 8\n\t" + "addi.w %2, %2, -1\n\t" + "bnez %2, 1b\n\t" + : "=r" ( discard_subtrahend ), + "=r" ( discard_value ), + "=r" ( discard_size ), + "=r" ( discard_subtrahend_i ), + "=r" ( discard_value_i ), + "=r" ( discard_carry ), + "=r" ( discard_temp ), + "+m" ( *value ) + : "0" ( subtrahend0 ), "1" ( value0 ), + "2" ( size ), "5" ( 0 ) ); } /** @@ -132,30 +143,37 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0, */ static inline __attribute__ (( always_inline )) void bigint_rol_raw ( uint64_t *value0, unsigned int size ) { + bigint_t ( size ) __attribute__ (( may_alias )) *value = + ( ( void * ) value0 ); uint64_t *discard_value; uint64_t discard_value_i; + uint64_t discard_carry; + uint64_t discard_temp; unsigned int discard_size; - uint64_t current_value_i; - unsigned int flag = 0; - discard_value = value0; - discard_size = size; - do { - discard_value_i = *discard_value; - current_value_i = discard_value_i; - - discard_value_i += discard_value_i + flag; - - if (discard_value_i < current_value_i) { - flag = 1; - } else { - flag = 0; - } - - *discard_value = discard_value_i; - discard_value++; - discard_size -= 1; - } while ( discard_size != 0 ); + __asm__ __volatile__ ( "\n1:\n\t" + /* Load value[i] */ + "ld.d %2, %0, 0\n\t" + /* Shift left */ + "rotri.d %2, %2, 63\n\t" + "andi %4, %2, 1\n\t" + "xor %2, %2, %4\n\t" + "or %2, %2, %3\n\t" + "move %3, %4\n\t" + /* Store value[i] */ + "st.d %2, %0, 0\n\t" + /* Loop */ + "addi.d %0, %0, 8\n\t" + "addi.w %1, %1, -1\n\t" + "bnez %1, 1b\n\t" + : "=r" ( discard_value ), + "=r" ( discard_size ), + "=r" ( discard_value_i ), + "=r" ( discard_carry ), + "=r" ( discard_temp ), + "+m" ( *value ) + : "0" ( value0 ), "1" ( size ), "3" ( 0 ) + : "cc" ); } /** @@ -166,27 +184,37 @@ bigint_rol_raw ( uint64_t *value0, unsigned int size ) { */ static inline __attribute__ (( always_inline )) void bigint_ror_raw ( uint64_t *value0, unsigned int size ) { + bigint_t ( size ) __attribute__ (( may_alias )) *value = + ( ( void * ) value0 ); uint64_t *discard_value; uint64_t discard_value_i; - uint64_t discard_value_j; + uint64_t discard_carry; + uint64_t discard_temp; unsigned int discard_size; - discard_value = value0; - discard_size = size; - - discard_value_j = 0; - - do { - discard_size -= 1; - - discard_value_i = *(discard_value + discard_size); - - discard_value_j = (discard_value_j << 63) | (discard_value_i >> 1); - - *(discard_value + discard_size) = discard_value_j; - - discard_value_j = discard_value_i; - } while ( discard_size > 0 ); + __asm__ __volatile__ ( "\n1:\n\t" + /* Load value[i] */ + "ld.d %2, %0, -8\n\t" + /* Shift right */ + "andi %4, %2, 1\n\t" + "xor %2, %2, %4\n\t" + "or %2, %2, %3\n\t" + "move %3, %4\n\t" + "rotri.d %2, %2, 1\n\t" + /* Store value[i] */ + "st.d %2, %0, -8\n\t" + /* Loop */ + "addi.d %0, %0, -8\n\t" + "addi.w %1, %1, -1\n\t" + "bnez %1, 1b\n\t" + : "=r" ( discard_value ), + "=r" ( discard_size ), + "=r" ( discard_value_i ), + "=r" ( discard_carry ), + "=r" ( discard_temp ), + "+m" ( *value ) + : "0" ( value0 + size ), "1" ( size ), "3" ( 0 ) + : "cc" ); } /** @@ -330,7 +358,9 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused, } extern void bigint_multiply_raw ( const uint64_t *multiplicand0, + unsigned int multiplicand_size, const uint64_t *multiplier0, - uint64_t *value0, unsigned int size ); + unsigned int multiplier_size, + uint64_t *value0 ); #endif /* _BITS_BIGINT_H */ diff --git a/src/arch/loong64/interface/efi/efiloong64_nap.c b/src/arch/loong64/interface/efi/efiloong64_nap.c index 5cd1c1b9..0a760978 100644 --- a/src/arch/loong64/interface/efi/efiloong64_nap.c +++ b/src/arch/loong64/interface/efi/efiloong64_nap.c @@ -46,8 +46,12 @@ static void efiloong64_cpu_nap ( void ) { * The EFI shell doesn't seem to bother sleeping the CPU; it * just sits there idly burning power. * + * If a shutdown is in progess, there may be nothing to + * generate an interrupt since the timer is disabled in the + * first step of ExitBootServices(). */ - __asm__ __volatile__ ( "idle 0" ); + if ( ! efi_shutdown_in_progress ) + __asm__ __volatile__ ( "idle 0" ); } PROVIDE_NAP ( efiloong64, cpu_nap, efiloong64_cpu_nap ); |