summaryrefslogtreecommitdiffstats
path: root/src/arch/x86/include/bits/bigint.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/include/bits/bigint.h')
-rw-r--r--src/arch/x86/include/bits/bigint.h108
1 files changed, 66 insertions, 42 deletions
diff --git a/src/arch/x86/include/bits/bigint.h b/src/arch/x86/include/bits/bigint.h
index a6bc2ca1d..21cffa0cf 100644
--- a/src/arch/x86/include/bits/bigint.h
+++ b/src/arch/x86/include/bits/bigint.h
@@ -7,6 +7,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
#include <string.h>
@@ -32,10 +33,12 @@ bigint_init_raw ( uint32_t *value0, unsigned int size,
long discard_c;
/* Copy raw data in reverse order, padding with zeros */
- __asm__ __volatile__ ( "\n1:\n\t"
+ __asm__ __volatile__ ( "jecxz 2f\n\t"
+ "\n1:\n\t"
"movb -1(%3,%1), %%al\n\t"
"stosb\n\t"
"loop 1b\n\t"
+ "\n2:\n\t"
"xorl %%eax, %%eax\n\t"
"mov %4, %1\n\t"
"rep stosb\n\t"
@@ -52,8 +55,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 flag
*/
-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 =
@@ -61,17 +65,20 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
long index;
void *discard_S;
long discard_c;
+ int carry;
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
"\n1:\n\t"
"lodsl\n\t"
- "adcl %%eax, (%4,%0,4)\n\t"
+ "adcl %%eax, (%5,%0,4)\n\t"
"inc %0\n\t" /* Does not affect CF */
"loop 1b\n\t"
: "=&r" ( index ), "=&S" ( discard_S ),
- "=&c" ( discard_c ), "+m" ( *value )
+ "=&c" ( discard_c ), "=@ccc" ( carry ),
+ "+m" ( *value )
: "r" ( value0 ), "1" ( addend0 ), "2" ( size )
: "eax" );
+ return carry;
}
/**
@@ -80,8 +87,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 flag
*/
-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 =
@@ -89,61 +97,71 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
long index;
void *discard_S;
long discard_c;
+ int borrow;
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
"\n1:\n\t"
"lodsl\n\t"
- "sbbl %%eax, (%4,%0,4)\n\t"
+ "sbbl %%eax, (%5,%0,4)\n\t"
"inc %0\n\t" /* Does not affect CF */
"loop 1b\n\t"
: "=&r" ( index ), "=&S" ( discard_S ),
- "=&c" ( discard_c ), "+m" ( *value )
+ "=&c" ( discard_c ), "=@ccc" ( borrow ),
+ "+m" ( *value )
: "r" ( value0 ), "1" ( subtrahend0 ),
"2" ( size )
: "eax" );
+ 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 );
long index;
long discard_c;
+ int out;
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
"\n1:\n\t"
- "rcll $1, (%3,%0,4)\n\t"
+ "rcll $1, (%4,%0,4)\n\t"
"inc %0\n\t" /* Does not affect CF */
"loop 1b\n\t"
: "=&r" ( index ), "=&c" ( discard_c ),
- "+m" ( *value )
+ "=@ccc" ( out ), "+m" ( *value )
: "r" ( value0 ), "1" ( size ) );
+ return out;
}
/**
- * 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 );
long discard_c;
+ int out;
__asm__ __volatile__ ( "clc\n\t"
"\n1:\n\t"
- "rcrl $1, -4(%2,%0,4)\n\t"
+ "rcrl $1, -4(%3,%0,4)\n\t"
"loop 1b\n\t"
- : "=&c" ( discard_c ), "+m" ( *value )
+ : "=&c" ( discard_c ), "=@ccc" ( out ),
+ "+m" ( *value )
: "r" ( value0 ), "0" ( size ) );
+ return out;
}
/**
@@ -196,25 +214,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
@@ -312,20 +311,45 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
long discard_c;
/* Copy raw data in reverse order */
- __asm__ __volatile__ ( "\n1:\n\t"
+ __asm__ __volatile__ ( "jecxz 2f\n\t"
+ "\n1:\n\t"
"movb -1(%3,%1), %%al\n\t"
"stosb\n\t"
"loop 1b\n\t"
+ "\n2:\n\t"
: "=&D" ( discard_D ), "=&c" ( discard_c ),
"+m" ( *out_bytes )
: "r" ( value0 ), "0" ( out ), "1" ( len )
: "eax" );
}
-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_a;
+
+ __asm__ __volatile__ ( /* Perform multiplication */
+ "mull %3\n\t"
+ /* Accumulate carry */
+ "addl %5, %0\n\t"
+ "adcl $0, %1\n\t"
+ /* Accumulate result */
+ "addl %0, %2\n\t"
+ "adcl $0, %1\n\t"
+ : "=&a" ( discard_a ),
+ "=&d" ( *carry ),
+ "+m" ( *result )
+ : "g" ( multiplicand ),
+ "0" ( multiplier ),
+ "r" ( *carry ) );
+}
#endif /* _BITS_BIGINT_H */