diff options
Diffstat (limited to 'src/arch/loong64/include/bits/bigint.h')
-rw-r--r-- | src/arch/loong64/include/bits/bigint.h | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/src/arch/loong64/include/bits/bigint.h b/src/arch/loong64/include/bits/bigint.h index bec748beb..ec6ca4b89 100644 --- a/src/arch/loong64/include/bits/bigint.h +++ b/src/arch/loong64/include/bits/bigint.h @@ -357,10 +357,42 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused, *(--out_byte) = *(value_byte++); } -extern void bigint_multiply_raw ( const uint64_t *multiplicand0, - unsigned int multiplicand_size, - const uint64_t *multiplier0, - unsigned int multiplier_size, - uint64_t *value0 ); +/** + * Multiply big integer elements + * + * @v multiplicand Multiplicand element + * @v multiplier Multiplier element + * @v result Result element pair + * @v carry Carry element + */ +static inline __attribute__ (( always_inline )) void +bigint_multiply_one ( const uint64_t multiplicand, const uint64_t multiplier, + uint64_t *result, uint64_t *carry ) { + uint64_t discard_low; + uint64_t discard_high; + uint64_t discard_carry; + + __asm__ __volatile__ ( /* Perform multiplication */ + "mul.d %0, %6, %7\n\t" + "mulh.du %1, %6, %7\n\t" + /* Accumulate low half */ + "add.d %3, %3, %0\n\t" + "sltu %2, %3, %0\n\t" + /* Add carry to high half (cannot overflow) */ + "add.d %1, %1, %2\n\t" + /* Accumulate high half */ + "add.d %4, %4, %1\n\t" + "sltu %2, %4, %1\n\t" + /* Accumulate carry (cannot overflow) */ + "add.d %5, %5, %2\n\t" + : "=&r" ( discard_low ), + "=r" ( discard_high ), + "=r" ( discard_carry ), + "+r" ( result[0] ), + "+r" ( result[1] ), + "+r" ( *carry ) + : "r" ( multiplicand ), + "r" ( multiplier ) ); +} #endif /* _BITS_BIGINT_H */ |