Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
AsmMultCodegenerator.py
Go to the documentation of this file.
1#!/usr/bin/env sage -python
2
3
4# how to call
5# sage -python AsmMultCodegenerator.py > fp9216.s
6
7from sage.all import *
8import math
9
10#///////////////////////////////////////////////////
11#//p word extractor [repeat pword times]
12def WordExtractor(p, pwords, Var):
13
14 k = 64
15 PWord = []
16 S = ".global " + Var + "\n" + Var + ":\n"
17
18 pp = p
19
20 for i in range(1,pwords+1):
21 if (((i - 1)%4) == 0):
22 S = S + ".quad "
23 #PWord[i] = pp%2**k
24 PWord.append(pp%2**k)
25 if((i%4) != 0):
26 #S = S + str(hex(PWord[i-1])).upper() + ","
27 S = S + "0x{:X}".format(PWord[i-1]) + ","
28 else:
29 #S = S + str(hex(PWord[i-1])).upper() + " \n"
30 S = S + "0x{:X}".format(PWord[i-1]) + " \n"
31 pp = pp // (2**k)
32
33 S = S + "\n\n"
34
35 print(S)
36 return S
37
38
39#//////////////////////////////////////////////////////////////////
40def PrintHeader(pbits, pbytes, plimbs):
41
42 S = ".intel_syntax noprefix\n\n"
43 S = S + ".section .rodata\n\n"
44 S = S + ".set pbits," + str(pbits) + "\n"
45 S = S + ".set pbytes," + str(pbytes) + "\n"
46 S = S + ".set plimbs," + str(plimbs) + "\n\n"
47 print(S)
48 return S
49
50#//////////////////////////////////////////////////////////////////
51def PrintUintHeader(plimbs):
52
53 S = ".intel_syntax noprefix\n\n"
54 S = S + ".section .rodata\n\n"
55 S = S + ".global uintbig_1\nuintbig_1:\n"
56 S = S + " .quad 1, 0, 0, 0\n"
57
58 N = (plimbs//4) -1;
59 for i in range(1, N+1):
60 S = S + " .quad 0, 0, 0, 0\n"
61
62 N = plimbs%4;
63 if (N != 0):
64 S = S + " .quad"
65 for i in range(1,N):
66 S = S + " 0,"
67 S = S + "0\n"
68
69 S = S + ".section .text\n\n"
70
71 S = S + ".global uintbig_add\nuintbig_add:\n mov rax, [rsi + 0]\n add rax, [rdx + 0]\n mov [rdi + 0], rax\n .set k, 1\n"
72
73 S = S + " .rept " + str(plimbs-1) + "\n"
74
75 S = S + "mov rax, [rsi + 8*k]\n adc rax, [rdx + 8*k]\n mov [rdi + 8*k], rax\n .set k, k+1\n .endr\n setc al\n movzx rax, al\n ret\n\n"
76
77 S = S + ".global uintbig_sub\nuintbig_sub:\n mov rax, [rsi + 0]\n sub rax, [rdx + 0]\n mov [rdi + 0], rax\n .set k, 1\n"
78
79 S = S + " .rept " + str(plimbs-1) + "\n"
80
81 S = S + " mov rax, [rsi + 8*k]\n sbb rax, [rdx + 8*k]\n mov [rdi + 8*k], rax\n .set k, k+1\n .endr\n setc al\n movzx rax, al\n ret"
82
83 print(S)
84 return 0
85
86#////////////////////////////////////////
88
89 S = ".section .data\n\n"
90 S = S + ".global fpadd\nfpadd:\n .quad 0\n\n"
91 S = S + ".global fpsqr\nfpsqr:\n .quad 0\n\n"
92 S = S + ".global fpmul\nfpmul:\n .quad 0\n\n"
93 S = S + ".section .text\n\n.p2align 4,,15\n\n"
94 S = S + ".global init_counters\ninit_counters:\n movq [rip + fpadd], 0\n movq [rip + fpsqr], 0\n movq [rip + fpmul], 0\n ret\n\n"
95 S = S + ".global fp_copy\nfp_copy:\n cld\n mov rcx, plimbs\n rep movsq\n ret\n\n"
96 S = S + ".global fp_cswap\nfp_cswap:\n movzx rax, dl\n neg rax\n .set k, 0\n .rept plimbs\n mov rcx, [rdi + 8*k]\n"
97 S = S + "mov rdx, [rsi + 8*k]\n mov r8, rcx\n xor r8, rdx\n and r8, rax\n\n xor rcx, r8\n xor rdx, r8\n\n"
98 S = S + " mov [rdi + 8*k], rcx\n mov [rsi + 8*k], rdx\n\n .set k, k+1\n .endr\n ret\n\n"
99
100 print(S)
101 return S
102
103#////////////////////////////////////////
104def PrintRedOnce(pbytes):
105
106 Reg_Ar = ["rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11"]
107
108 S = ".reduce_once:\n push rbp\n mov rbp, rdi\n\n mov rdi, [rbp + 0]\n sub rdi, [rip + p + 0]\n"
109
110 N = pbytes-8
111
112 for i in range(8,N+1,8):
113 S = S + " mov " + Reg_Ar[(int(i/8) % 8)] + ", [rbp + " + str(i) + "]\n sbb " + Reg_Ar[(int(i/8) % 8)] + ", [rip + p + " + str(i) + "]\n"
114 if ((int((i+8)/8)%8) == 0) and (i != 0):
115 S = S + "\n"
116
117 S = S + "\n setnc al\n movzx rax, al\n neg rax\n\n"
118 S = S + ".macro cswap2, r, m\n xor \\r, \\m\n and \\r, rax\n xor \\m, \\r\n.endm\n\n\n"
119
120 n = -(int(pbytes/8) % 8) +8
121
122 for i in range(1, n+1):
123 S = S + " cswap2 " + Reg_Ar[i-1] + ", [rbp + " + str((pbytes-n*8)+(i-1)*8) + "]\n"
124
125
126 N = N - (n*8)
127 M = math.ceil(N/64)
128 for j in range(1, M+1):
129
130 S = S + "\n mov rdi, [rbp + 0]\n sub rdi, [rip + p + 0]\n"
131 for i in range(8,N+1,8):
132 S = S + " mov " + Reg_Ar[int(i/8) % 8] + ", [rbp + " + str(i) + "]\n sbb " + Reg_Ar[int(i/8) % 8] + ", [rip + p + " + str(i) + "]\n"
133 if ((int((i+8)/8)%8) == 0) and (i != 0):
134 S = S + "\n"
135 for i in range(1,9):
136 S = S + " cswap2 " + Reg_Ar[i-1] + ", [rbp + " + str((N-64)+i*8) + "]\n"
137 N = N - 64
138
139 S = S + " pop rbp\n ret\n\n"
140
141 print(S)
142 return S
143
144#////////////////////////////////////////
146
147 S= ".global fp_add2\nfp_add2:\n mov rdx, rdi\n\n"
148 S = S + ".global fp_add\nfp_add:\n push rdi\n call uintbig_add\n pop rdi\n\n incq [rip + fpadd]\n\n jmp .reduce_once\n\n"
149 S = S + ".global fp_sub2\nfp_sub2:\n mov rdx, rdi\n xchg rsi, rdx\n\n.global fp_sub\nfp_sub:\n push rdi\n call uintbig_sub\n pop rdi\n\n\n"
150 S = S + " incq [rip + fpadd] /* increasing number of additions performed */\n\n neg rax\n\n sub rsp, pbytes\n\n"
151 S = S + " mov rcx, [rip + p + 0]\n and rcx, rax\n mov [rsp + 0],rcx\n .set k, 1\n .rept plimbs-1\n mov rcx, [rip + p + 8*k]\n and rcx, rax\n"
152 S = S + " mov [rsp + 8*k], rcx\n .set k, k+1\n .endr\n\n"
153 S = S + " mov rcx, [rsp + 0]\n add rcx, [rdi + 0]\n mov [rdi + 0], rcx\n .set k, 1\n .rept plimbs-1\n mov rcx, [rsp + 8*k]\n"
154 S = S + " adc rcx, [rdi + 8*k]\n mov [rdi + 8*k], rcx\n .set k, k+1\n .endr\n\n add rsp, pbytes\n ret\n\n\n"
155 S = S + "/* Montgomery arithmetic */\n\n.global fp_enc\nfp_enc:\n lea rdx, [rip + r_squared_mod_p]\n jmp fp_mul\n\n"
156 S = S + ".global fp_dec\nfp_dec:\n lea rdx, [rip + uintbig_1]\n jmp fp_mul\n\n\n"
157
158 print(S)
159 return S
160
161#////////////////////////////////////////
162def PrintMul(pbytes, pwords):
163
164 Reg_Ar = ["rbx", "rcx"]
165
166 S = ".global fp_mul2\nfp_mul2:\n mov rdx, rdi\n.global fp_mul\nfp_mul:\n push rbp\n push rbx\n\n"
167 S = S +" incq [rip + fpmul] /* increasing number of multiplications performed */\n\n"
168
169 S = S + " sub rsp, " + str(pbytes + 16) + "\n mov [rsp+ " + str(pbytes+8) + "],rdi\n mov rdi,rsi\n mov rsi,rdx\n\n\n"
170 S = S + " xor rax,rax\n"
171
172 N = pbytes
173
174 for i in range(0,N+1,8):
175 S = S + " mov [rsp+" + str(i) + "],rax\n"
176
177
178
179 S = S + "\n\n.macro MULSTEP, k, "
180 R = ""
181 for i in range(0, pwords):
182 R = ""
183 R = R + "I" + str(i) + ","
184 S = S + R
185
186 S = S + "I" + str(pwords) + "\n\n"
187 S = S + " mov r11,[rsp+\\I0]\n mov rdx, [rsi + 0]\n mulx rcx, rdx, [rdi + 8*\\k]\n add rdx, r11\n mulx rcx, rdx, [rip + inv_min_p_mod_r]"
188 S = S + "\n\n xor rax, rax /* clear flags */\n\n\n"
189
190 S = S + " mulx rbx, rax, [rip + p + 0]\n adox r11, rax\n mov [rsp+\\I0], r11\n\n"
191
192 N = pbytes-8
193
194 for i in range(8,N+1,8):
195 S = S + " mov r11,[rsp+\\I" + str(int(i/8)) + "]\n mulx " + Reg_Ar[(int(i/8) % 2)] + ", rax, [rip + p + " + str(i) + "]\n "
196 S = S + " adcx r11, " + Reg_Ar[-(int(i/8) % 2) +1] + "\n adox r11, rax\n mov [rsp+\\I" + str(int(i/8)) + "],r11\n\n"
197
198 S = S + "\n mov r11,[rsp+\\I" + str(pwords) + "]\n mov rax, 0\n adcx r11, rcx\n adox r11, rax\n mov [rsp+\\I" + str(pwords) + "],r11\n\n"
199 S = S + " mov rdx, [rdi + 8*\\k]\n\n xor rax, rax /* clear flags */\n\n"
200
201 S = S + " mov r11,[rsp+\\I0]\n mulx rbx, rax, [rsi + 0]\n adox r11, rax\n mov [rsp+\\I0],r11\n\n"
202
203 for i in range(8,N+1,8):
204 S = S + " mov r11,[rsp+\\I" + str(int(i/8)) + "]\n mulx " + Reg_Ar[int(i/8) % 2] + ", rax, [rsi + " + str(i) + "]\n"
205 S = S + " adcx r11, " + Reg_Ar[-(int(i/8) % 2) +1] + "\n adox r11, rax\n mov [rsp+\\I" + str(int(i/8)) + "],r11\n\n"
206
207 S = S + " mov r11,[rsp+\\I" + str(pwords) + "]\n mov rax, 0\n adcx r11, rcx\n adox r11, rax\n mov [rsp+\\I" + str(pwords) + "],r11\n\n.endm\n\n"
208
209 T = ""
210 for i in range(0, pwords):
211 T = T + "MULSTEP " + str(i) + ","
212 for j in range(8,pbytes+1,8):
213 T = T + str((j + i*8) % (pbytes + 8)) + ","
214 S = S + T
215 T = ""
216 S = S + str((pbytes +8 + i*8) % (pbytes + 8)) + "\n"
217
218 S = S + "\n\n mov rdi,[rsp+" + str(pbytes+8) + "]\n\n"
219
220 for i in range(0,N+1,8):
221 S = S + " mov r11,[rsp+" + str(i) + "]\n mov [rdi+" + str(i) + "],r11\n"
222
223
224 S = S + " add rsp," + str(pbytes+16) + "\n\n pop rbx\n pop rbp\n\n jmp .reduce_once\n\n\n"
225 S = S + ".global fp_sq1\nfp_sq1:\n mov rsi, rdi\n.global fp_sqr\nfp_sqr:\n mov rdx, rsi\n\n decq [rip + fpmul]\n incq [rip + fpsqr]\n\n jmp fp_mul\n"
226
227
228 print(S)
229 return S
230
231
232#////////////////////////////////////////
233def PrintPow(pwords):
234
235 S = ".global fp_pow\nfp_pow:\n push rbx\n mov rbx, rsi\n push r12\n push r13\n push rdi\n sub rsp, pbytes\n\n"
236 S = S + " mov rsi, rdi\n mov rdi, rsp\n call fp_copy\n\n mov rdi, [rsp + pbytes]\n lea rsi, [rip + fp_1]\n call fp_copy\n\n"
237 S = S + ".macro POWSTEP, k\n mov r13, [rbx + 8*\\k]\n xor r12, r12\n\n"
238 S = S + " 0:\n test r13, 1\n jz 1f\n\n mov rdi, [rsp + pbytes]\n mov rsi, rsp\n call fp_mul2\n\n"
239 S = S + " 1:\n mov rdi, rsp\n call fp_sq1\n\n shr r13\n\n inc r12\n test r12, 64\n jz 0b\n.endm\n\n"
240
241 for i in range(0, pwords):
242 S = S + " POWSTEP " + str(i) + "\n"
243
244 S = S + " add rsp, pbytes+8\n pop r13\n pop r12\n pop rbx\n ret\n\n\n"
245
246 print(S)
247 return S
248
249#////////////////////////////////////////
251 S = ".global fp_inv\nfp_inv:\n lea rsi, [rip + p_minus_2]\n jmp fp_pow\n\n\n"
252 S = S + ".global fp_issquare\nfp_issquare:\n push rdi\n lea rsi, [rip + p_minus_1_halves]\n call fp_pow\n pop rdi\n\n"
253 S = S + " xor rax, rax\n .set k, 0\n .rept plimbs\n mov rsi, [rdi + 8*k]\n xor rsi, [rip + fp_1 + 8*k]\n or rax, rsi\n"
254 S = S + " .set k, k+1\n .endr\n test rax, rax\n setz al\n movzx rax, al\n ret\n\n\n"
255
256 S = S + ".global fp_random\nfp_random:\n\n push rdi\n mov rsi, pbytes\n call randombytes\n pop rdi\n"
257 S = S + " mov rax, 1\n shl rax, (pbits % 64)\n dec rax\n and [rdi + pbytes-8], rax\n\n .set k, plimbs-1\n .rept plimbs\n"
258 S = S + " mov rax, [rip + p + 8*k]\n cmp [rdi + 8*k], rax\n jge fp_random\n jl 0f\n .set k, k-1\n .endr\n 0:\n ret"
259
260 print(S)
261 return S
262
263#////////////////////////////////////////
264def Print_Parameters(p, pbits, pbytes, pwords):
265
266#// Montgomery parameter R
267 R = 2**(64*pwords)
268 RR = IntegerModRing(R)
269
270#//Extracting p words and saving in file
271 P = WordExtractor(p, pwords, "p");
272
273# // Computing -(1/p) mod R;
274 #pinv = IntegerRing()!(RR!(-1/p))
275 pinv = int(RR(-p).inverse_of_unit())
276 #pinv = -(1//p)%R
277
278# //Extracting pinv words and saving in file
279 Pinv = WordExtractor(pinv, pwords, "inv_min_p_mod_r")
280
281# // Printing zero
282 S = ".global fp_0\nfp_0:\n.zero pbytes\n\n"
283 print(S)
284# PrintFile(Name, S);
285
286# // 1 at Montgomery domain
287 one = R%p
288
289# //Extracting one words and saving in file
290 ONE = WordExtractor(one, pwords, "fp_1")
291
292# // R^2 at Montgomery domain
293 Rsqr = R**2%p
294
295# //Extracting Rsqr words and saving in file
296 RsqrWords = WordExtractor(Rsqr, pwords, "r_squared_mod_p ")
297
298# //Extracting p-2 words and saving in file
299 pminus2Words = WordExtractor(p-2, pwords, "p_minus_2")
300
301# //Extracting phalves words and saving in file
302 phalvesWords = WordExtractor((p-1)//2, pwords, "p_minus_1_halves")
303
304# //Extracting pquarters words and saving in file
305 pquartersWords = WordExtractor((p-3)//4, pwords, "p_minus_3_quarters")
306
307# //Printing footer
308 S = PrintFooter()
309
310 return 0
311
312#////////////////////////////////////////
314
315#// size of p in bits, bytes ,words
316 pbits = math.ceil(math.log(p, 2.0))
317 pbytes = math.ceil(pbits/8)
318 if((pbytes%4) != 0):
319 pbytes = pbytes + 4 - (pbytes%4)
320 pwords = math.ceil(pbits/64)
321
322#// Writing header;
323 S = PrintHeader(pbits, pbytes, pwords)
324
325#// Writing parameters;
326 S = Print_Parameters(p, pbits, pbytes, pwords)
327
328#// Printing Reduce Once
329 S = PrintRedOnce(pbytes)
330
331#// Printing Add_Sub
332 S = PrintSub()
333
334#// Printing Mult
335 S = PrintMul(pbytes, pwords)
336
337#// Printing Pow
338 S = PrintPow(pwords)
339
340#// Printing Others
341 S = PrintOthers()
342
343 return 0;
344
345
346#//+++++++++++++++ Main ++++++++++++++++++//
347
348# Primes of the form p := 2^e * prod(ell_i's) - 1
349p_2047d221 = 0x5160D4543A2596D320C080B284C0FA5D3600AE4E29B85374858B238036139EA0B8B0C8B2850475382865FD4C9F7C3B5E531ED7D0FC022A13270300584EC78190FD09755A56CFEB1FC6961581CDFC56E824D0F31C4D4ECF04C5243CA0651820AF413023A7310203F74858FBECACA26B375BEBA9DE78CC420A069477B7FE595F83B148223C6841B3592C74AF79F39AE8F3D64F8B9FC946BB1C84A4541CBC2F363029B2C1E296158774A9646D2E186AD699B304FC7311F0DEC85E651756DDB4E3888D02333D591583AE5DB2F656E63A6179CDB059ED9BF90BAD614DCA5628C940C5004D99FB1CB03CE478F65726B12E42FA1C7C8FFFFFFFFFFFFFFFFFFFFFFFFFFF
350# Primes of the form p := 2^e - c
351p_4095d221 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5DCA635299EB2760CEDC3F12450C814FFA2DAFE875F09E8431F9BA694168EEF6A817F89E440736245D3D5615D75C648E8F90A3A4C6D12637CCD73F0B737F1AC09AF7B08CC11A71C4828DD80E16A08A29B57FB1322C6CF36BFD7B3C80A74000006EC3E89EA92275375DDAFD803BAF91F015F8218A5656A5785B5D8AAD338C9A4B887C3C7F367CC427744A1769686187B788DE2A6779C85A68380A7D2B7CC3B5FD680BC2708E20D188C0C320B3BF35B180FB234C85A0B72C5CE482CABE61EA58A6E2DD0FF11C5961E04B98980F9F1AF33B32E3E95171509454DFC9D28084903267459D8A3E22C44CB499384AB50DF44F65298B
352p_5119d256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE89A36D0A7F27637A69FA7A62E0497BC63E3F1C816F32AEAF17F7839D6750A178BB4B691A9922EAB7C9634D0F1491712278F84DA8FC1F472A05D101B8BE9CA1C44282F3AB0B081029CA3967363106F6FCB8542CFEBF9ED83C4B3A35DB0FC42E1FC21CFD1182E49B993A080BC3275B94EA17F8FBB0D7D4BCB3049D6C140A1869043F6460543CD4FEEDEED8D712D6419FE70166C3B8AECA00FACF147447A84B234E2851C58EAE204D626ACE863146FB74EB684C022F3BF3B8BF2CDA4F7A93742D0FB1BCEB40E0E8B01D90C4AFF7ED5B0050F67E9BF0C4A45B73197DE6FF68894CAE2C7B5846A541E178D4FCD073E1282F4488C33A0BFD91BFD26762233E12C84111AEB5BCD7C4C4A5ABFB99C416A83A8637CCF0F4A50FB6B4281CAF7EE5290777B47
353p_6143d306 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8BCBFA770CD08125807E305692E3C85B91BF0FD94B1AA66D620CD5AFDC3FD8B70B2F4A6D658EB2C108D85F2FC4A7F0EBA11711559966812FEAB4D8146C14F63D4F6C2DDF7F95E57D79A1708A70B938D443A33F6414F596193254946C057E55E0EB64468AA7C74E27D4262760A518B88CD7416F87BFD6B50C1FA2F9632E83D3532E4C54DF2610070E2260AA68098D41D32ED17EBEF25AD80291737FCE124CA40B14CD8D2A541D7E7EE43B59BE50C34D88B9DBDDF0913E701827191891890BA18B4442C4616112857E33749315DC057E74137968E068ED50E366915A615D18677497F66D95620EA399670B8957BCB31FF0D04FCD7420DB636851A46A1C8F8E9335FB5A3231D0CC421605228CD7544FAD284FB65FBAB19A1D943894FDD32A95F2D3A4EAF0C54C75070ED12E86EF0BD593B69D11DADCF4C4CC9AE8F9F58286E779E101D4E920E9EA883676B558C2E054F62AB63B52A0466D1D8D558ACE1EE2DE0305CB1A97233
354p_8191d306 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0005092EFE1954EBB40A5CC43278D477FD9E3EAB895B8F2DDBE5B21E0CFE797534FB57593D9CED0575EDB5B3C891BCD97F5C24D8225ED6BF593503E0E92D16B5817930E596246C7D9FA5C4E69BD697E5785E4029A6FCE266873B20072D9D77FBE3A6787D9505832B1C4CB8FBF8182DE87845FB05729FE0EB5D2E78E15A941D41085E07E5ABDBB810BA0B0CDA857D73EFEF39F186CA5B351388824A4401AD9C705758DD32F6A24BD885A87DE91F2ACB13EE80A20603BA5902790CB5A4DBA62746649523DE1E2E9EF976A1F71A5540135C50F4E2DA7E1DFBD362CC30CCEAEA80B9566007E22803F27E88038BA93DEFDCC41B1CC4AFE87D59271537740DB1E90108F580E913FDC38F9F2CA0009E839AB129D652A58322FAB0E170D65F12452E141AFE4B35F6ECFB3FC418A76092862349F03FBB55FA7711B3848BB2277A7F27EA7B2B5A1BEDF1BBF3302E59F5EC70E356FED1AE90629595BCA065091757DF032885E148C0DAB
355p_9215d384 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCBA9E8D0D6E9647C535CB46390ED91FC7AB7043EB5A9C26EB56EBB88454A58C04553995209FDB2410C9C67866931FEAFC080BB4CC7FA187C8EA2BC31840C389EDBAEE5977D5A481BB874F0570EB0A90B188BF78E3116848B9F422B6BDC79FCFA5BEB1C951A307D90FA5A04E6D9BF026EBAFD375694158D9D49691E5D417608B3F969E83C4B10384F42A9D12ED50AA779290FB264E91A2E8C34A2DED0A3871578C01954350DF448D390A0E3F4A7B11F5B679A57CF74CDF1379FB85BC333D2984CD67DF800211ED3B655081ACF4283069139E3C1038A7E7CA1C359D6E1419E1595C3BCD44506EF8433ABA1C7C256A52C3798F0C512A845833F9CE9FE55E8DD29533658843F47960E92EE2CDDCFB5536967C535FE8CCC9E9C8D344E0F4E313378066BF91B95A5337EE185D4467A2C4D4B5997B38F79B7FB7B42C375B29A38B8F5C8069057CAC67235E887B4D8159BE72AE32E14D0FFD1B42A3FF326055B4C328CDAD6A75F5B23C399998F5DE800FEFECD8B3AFDAE00255184CB60E24E43A457BB6F7BE3D0421CEC679680564CE765691B9C8389AC3633D15CF94E29C45F1979022217553F152DB66127808BF4FFD6CD2BB454D63222DF2E9B7DC4A6ABDD88150FB50DA44CBAF5160B27205E82C68E055EF2EE83
356
357# NIST LEVEL 1
358#p = p_2047d221
359p = p_4095d221
360#p = p_5119d256
361# NIST LEVEL 3
362#p = p_6143d306
363#p = p_8191d306
364#p = p_9215d384
365
366n = math.ceil(math.log(p, 2.0))
367
368if (n % 64) != 0:
369 n = n + 64 - (n%64)
370
372#PrintUintHeader(n//64)
Print_Parameters(p, pbits, pbytes, pwords)
PrintHeader(pbits, pbytes, plimbs)
WordExtractor(p, pwords, Var)
end if