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.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. #include <strings.h>
  11. /** Element of a big integer */
  12. typedef uint32_t bigint_element_t;
  13. /**
  14. * Initialise big integer
  15. *
  16. * @v value0 Element 0 of big integer to initialise
  17. * @v size Number of elements
  18. * @v data Raw data
  19. * @v len Length of raw data
  20. */
  21. static inline __attribute__ (( always_inline )) void
  22. bigint_init_raw ( uint32_t *value0, unsigned int size,
  23. const void *data, size_t len ) {
  24. size_t pad_len = ( sizeof ( bigint_t ( size ) ) - len );
  25. uint8_t *value_byte = ( ( void * ) value0 );
  26. const uint8_t *data_byte = ( data + len );
  27. /* Copy raw data in reverse order, padding with zeros */
  28. while ( len-- )
  29. *(value_byte++) = *(--data_byte);
  30. while ( pad_len-- )
  31. *(value_byte++) = 0;
  32. }
  33. /**
  34. * Add big integers
  35. *
  36. * @v addend0 Element 0 of big integer to add
  37. * @v value0 Element 0 of big integer to be added to
  38. * @v size Number of elements
  39. */
  40. static inline __attribute__ (( always_inline )) void
  41. bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
  42. unsigned int size ) {
  43. bigint_t ( size ) __attribute__ (( may_alias )) *value =
  44. ( ( void * ) value0 );
  45. uint32_t *discard_addend;
  46. uint32_t *discard_value;
  47. uint32_t *discard_end;
  48. uint32_t discard_addend_i;
  49. uint32_t discard_value_i;
  50. __asm__ __volatile__ ( "adds %2, %0, %8, lsl #2\n\t" /* clear CF */
  51. "\n1:\n\t"
  52. "ldmia %0!, {%3}\n\t"
  53. "ldr %4, [%1]\n\t"
  54. "adcs %4, %3\n\t"
  55. "stmia %1!, {%4}\n\t"
  56. "teq %0, %2\n\t"
  57. "bne 1b\n\t"
  58. : "=l" ( discard_addend ),
  59. "=l" ( discard_value ),
  60. "=l" ( discard_end ),
  61. "=l" ( discard_addend_i ),
  62. "=l" ( discard_value_i ),
  63. "+m" ( *value )
  64. : "0" ( addend0 ), "1" ( value0 ), "l" ( size )
  65. : "cc" );
  66. }
  67. /**
  68. * Subtract big integers
  69. *
  70. * @v subtrahend0 Element 0 of big integer to subtract
  71. * @v value0 Element 0 of big integer to be subtracted from
  72. * @v size Number of elements
  73. */
  74. static inline __attribute__ (( always_inline )) void
  75. bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
  76. unsigned int size ) {
  77. bigint_t ( size ) __attribute__ (( may_alias )) *value =
  78. ( ( void * ) value0 );
  79. uint32_t *discard_subtrahend;
  80. uint32_t *discard_value;
  81. uint32_t *discard_end;
  82. uint32_t discard_subtrahend_i;
  83. uint32_t discard_value_i;
  84. __asm__ __volatile__ ( "add %2, %0, %8, lsl #2\n\t"
  85. "cmp %2, %0\n\t" /* set CF */
  86. "\n1:\n\t"
  87. "ldmia %0!, {%3}\n\t"
  88. "ldr %4, [%1]\n\t"
  89. "sbcs %4, %3\n\t"
  90. "stmia %1!, {%4}\n\t"
  91. "teq %0, %2\n\t"
  92. "bne 1b\n\t"
  93. : "=l" ( discard_subtrahend ),
  94. "=l" ( discard_value ),
  95. "=l" ( discard_end ),
  96. "=l" ( discard_subtrahend_i ),
  97. "=l" ( discard_value_i ),
  98. "+m" ( *value )
  99. : "0" ( subtrahend0 ), "1" ( value0 ),
  100. "l" ( size )
  101. : "cc" );
  102. }
  103. /**
  104. * Rotate big integer left
  105. *
  106. * @v value0 Element 0 of big integer
  107. * @v size Number of elements
  108. */
  109. static inline __attribute__ (( always_inline )) void
  110. bigint_rol_raw ( uint32_t *value0, unsigned int size ) {
  111. bigint_t ( size ) __attribute__ (( may_alias )) *value =
  112. ( ( void * ) value0 );
  113. uint32_t *discard_value;
  114. uint32_t *discard_end;
  115. uint32_t discard_value_i;
  116. __asm__ __volatile__ ( "adds %1, %0, %5, lsl #2\n\t" /* clear CF */
  117. "\n1:\n\t"
  118. "ldr %2, [%0]\n\t"
  119. "adcs %2, %2\n\t"
  120. "stmia %0!, {%2}\n\t"
  121. "teq %0, %1\n\t"
  122. "bne 1b\n\t"
  123. : "=l" ( discard_value ),
  124. "=l" ( discard_end ),
  125. "=l" ( discard_value_i ),
  126. "+m" ( *value )
  127. : "0" ( value0 ), "1" ( size )
  128. : "cc" );
  129. }
  130. /**
  131. * Rotate big integer right
  132. *
  133. * @v value0 Element 0 of big integer
  134. * @v size Number of elements
  135. */
  136. static inline __attribute__ (( always_inline )) void
  137. bigint_ror_raw ( uint32_t *value0, unsigned int size ) {
  138. bigint_t ( size ) __attribute__ (( may_alias )) *value =
  139. ( ( void * ) value0 );
  140. uint32_t *discard_value;
  141. uint32_t *discard_end;
  142. uint32_t discard_value_i;
  143. __asm__ __volatile__ ( "adds %1, %0, %5, lsl #2\n\t" /* clear CF */
  144. "\n1:\n\t"
  145. "ldmdb %1!, {%2}\n\t"
  146. "rrxs %2, %2\n\t"
  147. "str %2, [%1]\n\t"
  148. "teq %0, %1\n\t"
  149. "bne 1b\n\t"
  150. : "=l" ( discard_value ),
  151. "=l" ( discard_end ),
  152. "=l" ( discard_value_i ),
  153. "+m" ( *value )
  154. : "0" ( value0 ), "1" ( size )
  155. : "cc" );
  156. }
  157. /**
  158. * Test if big integer is equal to zero
  159. *
  160. * @v value0 Element 0 of big integer
  161. * @v size Number of elements
  162. * @ret is_zero Big integer is equal to zero
  163. */
  164. static inline __attribute__ (( always_inline, pure )) int
  165. bigint_is_zero_raw ( const uint32_t *value0, unsigned int size ) {
  166. const uint32_t *value = value0;
  167. uint32_t value_i;
  168. do {
  169. value_i = *(value++);
  170. if ( value_i )
  171. break;
  172. } while ( --size );
  173. return ( value_i == 0 );
  174. }
  175. /**
  176. * Compare big integers
  177. *
  178. * @v value0 Element 0 of big integer
  179. * @v reference0 Element 0 of reference big integer
  180. * @v size Number of elements
  181. * @ret geq Big integer is greater than or equal to the reference
  182. */
  183. static inline __attribute__ (( always_inline, pure )) int
  184. bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0,
  185. unsigned int size ) {
  186. const uint32_t *value = ( value0 + size );
  187. const uint32_t *reference = ( reference0 + size );
  188. uint32_t value_i;
  189. uint32_t reference_i;
  190. do {
  191. value_i = *(--value);
  192. reference_i = *(--reference);
  193. if ( value_i != reference_i )
  194. break;
  195. } while ( --size );
  196. return ( value_i >= reference_i );
  197. }
  198. /**
  199. * Test if bit is set in big integer
  200. *
  201. * @v value0 Element 0 of big integer
  202. * @v size Number of elements
  203. * @v bit Bit to test
  204. * @ret is_set Bit is set
  205. */
  206. static inline __attribute__ (( always_inline )) int
  207. bigint_bit_is_set_raw ( const uint32_t *value0, unsigned int size,
  208. unsigned int bit ) {
  209. const bigint_t ( size ) __attribute__ (( may_alias )) *value =
  210. ( ( const void * ) value0 );
  211. unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
  212. unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
  213. return ( value->element[index] & ( 1 << subindex ) );
  214. }
  215. /**
  216. * Find highest bit set in big integer
  217. *
  218. * @v value0 Element 0 of big integer
  219. * @v size Number of elements
  220. * @ret max_bit Highest bit set + 1 (or 0 if no bits set)
  221. */
  222. static inline __attribute__ (( always_inline )) int
  223. bigint_max_set_bit_raw ( const uint32_t *value0, unsigned int size ) {
  224. const uint32_t *value = ( value0 + size );
  225. int max_bit = ( 8 * sizeof ( bigint_t ( size ) ) );
  226. uint32_t value_i;
  227. do {
  228. value_i = *(--value);
  229. max_bit -= ( 32 - fls ( value_i ) );
  230. if ( value_i )
  231. break;
  232. } while ( --size );
  233. return max_bit;
  234. }
  235. /**
  236. * Grow big integer
  237. *
  238. * @v source0 Element 0 of source big integer
  239. * @v source_size Number of elements in source big integer
  240. * @v dest0 Element 0 of destination big integer
  241. * @v dest_size Number of elements in destination big integer
  242. */
  243. static inline __attribute__ (( always_inline )) void
  244. bigint_grow_raw ( const uint32_t *source0, unsigned int source_size,
  245. uint32_t *dest0, unsigned int dest_size ) {
  246. unsigned int pad_size = ( dest_size - source_size );
  247. memcpy ( dest0, source0, sizeof ( bigint_t ( source_size ) ) );
  248. memset ( ( dest0 + source_size ), 0, sizeof ( bigint_t ( pad_size ) ) );
  249. }
  250. /**
  251. * Shrink big integer
  252. *
  253. * @v source0 Element 0 of source big integer
  254. * @v source_size Number of elements in source big integer
  255. * @v dest0 Element 0 of destination big integer
  256. * @v dest_size Number of elements in destination big integer
  257. */
  258. static inline __attribute__ (( always_inline )) void
  259. bigint_shrink_raw ( const uint32_t *source0, unsigned int source_size __unused,
  260. uint32_t *dest0, unsigned int dest_size ) {
  261. memcpy ( dest0, source0, sizeof ( bigint_t ( dest_size ) ) );
  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. const uint8_t *value_byte = ( ( const void * ) value0 );
  275. uint8_t *out_byte = ( out + len );
  276. /* Copy raw data in reverse order */
  277. while ( len-- )
  278. *(--out_byte) = *(value_byte++);
  279. }
  280. extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
  281. const uint32_t *multiplier0,
  282. uint32_t *value0, unsigned int size );
  283. #endif /* _BITS_BIGINT_H */