summaryrefslogtreecommitdiffstats
path: root/src/arch/loong64
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/loong64')
-rw-r--r--src/arch/loong64/core/loong64_bigint.c26
-rw-r--r--src/arch/loong64/include/bits/bigint.h188
-rw-r--r--src/arch/loong64/interface/efi/efiloong64_nap.c6
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 );