You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bigint.h 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #ifndef _BITS_BIGINT_H
  2. #define _BITS_BIGINT_H
  3. /** @file
  4. *
  5. * Big integer support
  6. */
  7. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  8. #include <stdint.h>
  9. #include <string.h>
  10. /** Element of a big integer */
  11. typedef uint32_t bigint_element_t;
  12. /**
  13. * Initialise big integer
  14. *
  15. * @v value0 Element 0 of big integer to initialise
  16. * @v size Number of elements
  17. * @v data Raw data
  18. * @v len Length of raw data
  19. */
  20. static inline __attribute__ (( always_inline )) void
  21. bigint_init_raw ( uint32_t *value0, unsigned int size,
  22. const void *data, size_t len ) {
  23. long pad_len = ( sizeof ( bigint_t ( size ) ) - len );
  24. void *discard_D;
  25. long discard_c;
  26. /* Copy raw data in reverse order, padding with zeros */
  27. __asm__ __volatile__ ( "\n1:\n\t"
  28. "movb -1(%2,%1), %%al\n\t"
  29. "stosb\n\t"
  30. "loop 1b\n\t"
  31. "xorl %%eax, %%eax\n\t"
  32. "mov %3, %1\n\t"
  33. "rep stosb\n\t"
  34. : "=&D" ( discard_D ), "=&c" ( discard_c )
  35. : "r" ( data ), "g" ( pad_len ), "0" ( value0 ),
  36. "1" ( len )
  37. : "eax" );
  38. }
  39. /**
  40. * Add big integers
  41. *
  42. * @v addend0 Element 0 of big integer to add
  43. * @v value0 Element 0 of big integer to be added to
  44. * @v size Number of elements
  45. */
  46. static inline __attribute__ (( always_inline )) void
  47. bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
  48. unsigned int size ) {
  49. long index;
  50. void *discard_S;
  51. long discard_c;
  52. __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
  53. "\n1:\n\t"
  54. "lodsl\n\t"
  55. "adcl %%eax, (%3,%0,4)\n\t"
  56. "inc %0\n\t" /* Does not affect CF */
  57. "loop 1b\n\t"
  58. : "=&r" ( index ), "=&S" ( discard_S ),
  59. "=&c" ( discard_c )
  60. : "r" ( value0 ), "1" ( addend0 ), "2" ( size )
  61. : "eax" );
  62. }
  63. /**
  64. * Subtract big integers
  65. *
  66. * @v subtrahend0 Element 0 of big integer to subtract
  67. * @v value0 Element 0 of big integer to be subtracted from
  68. * @v size Number of elements
  69. */
  70. static inline __attribute__ (( always_inline )) void
  71. bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
  72. unsigned int size ) {
  73. long index;
  74. void *discard_S;
  75. long discard_c;
  76. __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
  77. "\n1:\n\t"
  78. "lodsl\n\t"
  79. "sbbl %%eax, (%3,%0,4)\n\t"
  80. "inc %0\n\t" /* Does not affect CF */
  81. "loop 1b\n\t"
  82. : "=&r" ( index ), "=&S" ( discard_S ),
  83. "=&c" ( discard_c )
  84. : "r" ( value0 ), "1" ( subtrahend0 ),
  85. "2" ( size )
  86. : "eax" );
  87. }
  88. /**
  89. * Rotate big integer left
  90. *
  91. * @v value0 Element 0 of big integer
  92. * @v size Number of elements
  93. */
  94. static inline __attribute__ (( always_inline )) void
  95. bigint_rol_raw ( uint32_t *value0, unsigned int size ) {
  96. long index;
  97. long discard_c;
  98. __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
  99. "\n1:\n\t"
  100. "rcll $1, (%2,%0,4)\n\t"
  101. "inc %0\n\t" /* Does not affect CF */
  102. "loop 1b\n\t"
  103. : "=&r" ( index ), "=&c" ( discard_c )
  104. : "r" ( value0 ), "1" ( size ) );
  105. }
  106. /**
  107. * Rotate big integer right
  108. *
  109. * @v value0 Element 0 of big integer
  110. * @v size Number of elements
  111. */
  112. static inline __attribute__ (( always_inline )) void
  113. bigint_ror_raw ( uint32_t *value0, unsigned int size ) {
  114. long discard_c;
  115. __asm__ __volatile__ ( "clc\n\t"
  116. "\n1:\n\t"
  117. "rcrl $1, -4(%1,%0,4)\n\t"
  118. "loop 1b\n\t"
  119. : "=&c" ( discard_c )
  120. : "r" ( value0 ), "0" ( size ) );
  121. }
  122. /**
  123. * Test if big integer is equal to zero
  124. *
  125. * @v value0 Element 0 of big integer
  126. * @v size Number of elements
  127. * @ret is_zero Big integer is equal to zero
  128. */
  129. static inline __attribute__ (( always_inline, pure )) int
  130. bigint_is_zero_raw ( const uint32_t *value0, unsigned int size ) {
  131. void *discard_D;
  132. long discard_c;
  133. int result;
  134. __asm__ __volatile__ ( "xor %0, %0\n\t" /* Set ZF */
  135. "repe scasl\n\t"
  136. "sete %b0\n\t"
  137. : "=&a" ( result ), "=&D" ( discard_D ),
  138. "=&c" ( discard_c )
  139. : "1" ( value0 ), "2" ( size ) );
  140. return result;
  141. }
  142. /**
  143. * Compare big integers
  144. *
  145. * @v value0 Element 0 of big integer
  146. * @v reference0 Element 0 of reference big integer
  147. * @v size Number of elements
  148. * @ret geq Big integer is greater than or equal to the reference
  149. */
  150. static inline __attribute__ (( always_inline, pure )) int
  151. bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0,
  152. unsigned int size ) {
  153. const bigint_t ( size ) __attribute__ (( may_alias )) *value =
  154. ( ( const void * ) value0 );
  155. const bigint_t ( size ) __attribute__ (( may_alias )) *reference =
  156. ( ( const void * ) reference0 );
  157. void *discard_S;
  158. void *discard_D;
  159. long discard_c;
  160. int result;
  161. __asm__ __volatile__ ( "std\n\t"
  162. "\n1:\n\t"
  163. "lodsl\n\t"
  164. "scasl\n\t"
  165. "loope 1b\n\t"
  166. "setae %b0\n\t"
  167. "cld\n\t"
  168. : "=q" ( result ), "=&S" ( discard_S ),
  169. "=&D" ( discard_D ), "=&c" ( discard_c )
  170. : "0" ( 0 ), "1" ( &value->element[ size - 1 ] ),
  171. "2" ( &reference->element[ size - 1 ] ),
  172. "3" ( size )
  173. : "eax" );
  174. return result;
  175. }
  176. /**
  177. * Test if bit is set in big integer
  178. *
  179. * @v value0 Element 0 of big integer
  180. * @v size Number of elements
  181. * @v bit Bit to test
  182. * @ret is_set Bit is set
  183. */
  184. static inline __attribute__ (( always_inline )) int
  185. bigint_bit_is_set_raw ( const uint32_t *value0, unsigned int size,
  186. unsigned int bit ) {
  187. const bigint_t ( size ) __attribute__ (( may_alias )) *value =
  188. ( ( const void * ) value0 );
  189. unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
  190. unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
  191. return ( value->element[index] & ( 1 << subindex ) );
  192. }
  193. /**
  194. * Find highest bit set in big integer
  195. *
  196. * @v value0 Element 0 of big integer
  197. * @v size Number of elements
  198. * @ret max_bit Highest bit set + 1 (or 0 if no bits set)
  199. */
  200. static inline __attribute__ (( always_inline )) int
  201. bigint_max_set_bit_raw ( const uint32_t *value0, unsigned int size ) {
  202. long discard_c;
  203. int result;
  204. __asm__ __volatile__ ( "\n1:\n\t"
  205. "bsrl -4(%2,%1,4), %0\n\t"
  206. "loopz 1b\n\t"
  207. "rol %1\n\t" /* Does not affect ZF */
  208. "rol %1\n\t"
  209. "leal 1(%k0,%k1,8), %k0\n\t"
  210. "jnz 2f\n\t"
  211. "xor %0, %0\n\t"
  212. "\n2:\n\t"
  213. : "=&r" ( result ), "=&c" ( discard_c )
  214. : "r" ( value0 ), "1" ( size ) );
  215. return result;
  216. }
  217. /**
  218. * Grow big integer
  219. *
  220. * @v source0 Element 0 of source big integer
  221. * @v source_size Number of elements in source big integer
  222. * @v dest0 Element 0 of destination big integer
  223. * @v dest_size Number of elements in destination big integer
  224. */
  225. static inline __attribute__ (( always_inline )) void
  226. bigint_grow_raw ( const uint32_t *source0, unsigned int source_size,
  227. uint32_t *dest0, unsigned int dest_size ) {
  228. long pad_size = ( dest_size - source_size );
  229. void *discard_D;
  230. void *discard_S;
  231. long discard_c;
  232. __asm__ __volatile__ ( "rep movsl\n\t"
  233. "xorl %%eax, %%eax\n\t"
  234. "mov %3, %2\n\t"
  235. "rep stosl\n\t"
  236. : "=&D" ( discard_D ), "=&S" ( discard_S ),
  237. "=&c" ( discard_c )
  238. : "g" ( pad_size ), "0" ( dest0 ),
  239. "1" ( source0 ), "2" ( source_size )
  240. : "eax" );
  241. }
  242. /**
  243. * Shrink big integer
  244. *
  245. * @v source0 Element 0 of source big integer
  246. * @v source_size Number of elements in source big integer
  247. * @v dest0 Element 0 of destination big integer
  248. * @v dest_size Number of elements in destination big integer
  249. */
  250. static inline __attribute__ (( always_inline )) void
  251. bigint_shrink_raw ( const uint32_t *source0, unsigned int source_size __unused,
  252. uint32_t *dest0, unsigned int dest_size ) {
  253. void *discard_D;
  254. void *discard_S;
  255. long discard_c;
  256. __asm__ __volatile__ ( "rep movsl\n\t"
  257. : "=&D" ( discard_D ), "=&S" ( discard_S ),
  258. "=&c" ( discard_c )
  259. : "0" ( dest0 ), "1" ( source0 ),
  260. "2" ( dest_size )
  261. : "eax" );
  262. }
  263. /**
  264. * Finalise big integer
  265. *
  266. * @v value0 Element 0 of big integer to finalise
  267. * @v size Number of elements
  268. * @v out Output buffer
  269. * @v len Length of output buffer
  270. */
  271. static inline __attribute__ (( always_inline )) void
  272. bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
  273. void *out, size_t len ) {
  274. void *discard_D;
  275. long discard_c;
  276. /* Copy raw data in reverse order */
  277. __asm__ __volatile__ ( "\n1:\n\t"
  278. "movb -1(%2,%1), %%al\n\t"
  279. "stosb\n\t"
  280. "loop 1b\n\t"
  281. : "=&D" ( discard_D ), "=&c" ( discard_c )
  282. : "r" ( value0 ), "0" ( out ), "1" ( len )
  283. : "eax" );
  284. }
  285. extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
  286. const uint32_t *multiplier0,
  287. uint32_t *value0, unsigned int size );
  288. #endif /* _BITS_BIGINT_H */