circom/c/buildasm/old/fr.asm.ejs.old
c/buildasm/old/fr.asm.ejs.oldRaw
1
2
3 global <%=name%>_add
4 global <%=name%>_mul
5 global <%=name%>_q
6 DEFAULT REL
7
8 section .text
9
10;;;;;;;;;;;;;;;;;;;;;;
11; add
12;;;;;;;;;;;;;;;;;;;;;;
13<%=name%>_add:
14 ; Add component by component with carry
15<% for (let i=0; i<n64; i++) { %>
16 mov rax, [rsi + <%=i*8%>]
17 <%= i==0 ? "add" : "adc" %> rax, [rdx + <%=i*8%>]
18 mov [rdi + <%=i*8%>], rax
19<% } %>
20 jc add_sq ; if overflow, substract q
21
22 ; Compare with q
23<% for (let i=0; i<n64; i++) { %>
24<% if (i>0) { %>
25 mov rax, [rdi + <%= (n64-i-1)*8 %>]
26<% } %>
27 cmp rax, [q + <%= (n64-i-1)*8 %>]
28 jg add_sq
29 jl add_done
30<% } %>
31 ; If equal substract q
32add_sq:
33<% for (let i=0; i<n64; i++) { %>
34 mov rax, [q + <%=i*8%>]
35 <%= i==0 ? "sub" : "sbb" %> [rdi + <%=i*8%>], rax
36 mov [rdx + <%=i*8%>], rax
37<% } %>
38
39add_done:
40 ret
41
42
43;;;;;;;;;;;;;;;;;;;;;;
44; mul Montgomery
45;;;;;;;;;;;;;;;;;;;;;;
46mulM:
47<%
48let r0, r1, r2;
49function setR(step) {
50 if ((step % 3) == 0) {
51 r0 = "r8";
52 r1 = "r9";
53 r2 = "r10";
54 } else if ((step % 3) == 1) {
55 r0 = "r9";
56 r1 = "r10";
57 r2 = "r8";
58 } else {
59 r0 = "r10";
60 r1 = "r8";
61 r2 = "r9";
62 }
63}
64
65const base = bigInt.one.shiftLeft(64);
66const np64 = base.minus(q.modInv(base));
67%>
68 sub rsp, <%= n64*8 %> ; Reserve space for ms
69 mov rcx, rdx ; rdx is needed for multiplications so keep it in cx
70 mov r11, 0x<%= np64.toString(16) %> ; np
71 xor r8,r8
72 xor r9,r9
73 xor r10,r10
74<%
75// Main loop
76for (let i=0; i<n64*2; i++) {
77 setR(i);
78%>
79<%
80 // Same Digit
81 for (let o1=Math.max(0, i-n64+1); (o1<=i)&&(o1<n64); o1++) {
82 const o2= i-o1;
83%>
84 mov rax, [rsi + <%= 8*o1 %>]
85 mul qword [rcx + <%= 8*o2 %>]
86 add <%= r0 %>, rax
87 adc <%= r1 %>, rdx
88 adc <%= r2 %>, 0x0
89<%
90 } // Same digit
91%>
92
93
94<%
95 for (let j=i-1; j>=0; j--) { // All ms
96 if (((i-j)<n64)&&(j<n64)) {
97%>
98 mov rax, [rsp + <%= j*8 %>]
99 mul qword [q + <%= (i-j)*8 %>]
100 add <%= r0 %>, rax
101 adc <%= r1 %>, rdx
102 adc <%= r2 %>, 0x0
103<%
104 }
105 } // ms
106%>
107
108<%
109 if (i<n64) {
110%>
111 mov rax, <%= r0 %>
112 mul r11
113 mov [rsp + <%= i*8 %>], rax
114 mul qword [q]
115 add <%= r0 %>, rax
116 adc <%= r1 %>, rdx
117 adc <%= r2 %>, 0x0
118<%
119 } else {
120%>
121 mov [rdi + <%= (i-n64)*8 %> ], <%= r0 %>
122 xor <%= r0 %>,<%= r0 %>
123<%
124 }
125%>
126
127<%
128} // Main Loop
129%>
130 cmp <%= r1 %>, 0x0
131 jne mulM_sq
132 ; Compare with q
133<%
134for (let i=0; i<n64; i++) {
135%>
136 mov rax, [rdi + <%= (n64-i-1)*8 %>]
137 cmp rax, [q + <%= (n64-i-1)*8 %>]
138 jg mulM_sq
139 jl mulM_done
140<%
141}
142%>
143 ; If equal substract q
144
145mulM_sq:
146<%
147for (let i=0; i<n64; i++) {
148%>
149 mov rax, [q + <%= i*8 %>]
150 <%= i==0 ? "sub" : "sbb" %> [rdi + <%= i*8 %>], rax
151 mov [rdx + <%= i*8 %>], rax
152<%
153}
154%>
155
156mulM_done:
157 add rsp, <%= n64*8 %> ; recover rsp
158 ret
159
160;;;;;;;;;;;;;;;;;;;;;;
161; mul MontgomeryShort
162;;;;;;;;;;;;;;;;;;;;;;
163mulSM:
164
165;;;;;;;;;;;;;;;;;;;;;;
166; mul
167;;;;;;;;;;;;;;;;;;;;;;
168<%=name%>_mul:
169 mov rax, [rsi]
170 bt rax, 63
171 jc l1
172 mov rcx, [rdx]
173 bt rcx, 63
174 jc s1l2
175s1s2: ; short first and second
176 mul ecx
177 jc rs2l ; If if doesn't feed in 32 bits convert the result to long
178
179 ; The shorts multiplication is done. copy the val to destination and return
180 mov [rdi], rax
181 ret
182
183rs2l: ; The result in the multiplication doen't feed
184 ; we have the result in edx:eax we need to convert it to long
185 shl rdx, 32
186 mov edx, eax ; pack edx:eax to rdx
187
188 xor rax, rax ; Set the format to long
189 bts rax, 63
190 mov [rdi], rax ; move the first digit
191
192 cmp rdx, 0 ; check if redx is negative.
193 jl rs2ln
194
195 ; edx is positive.
196 mov [rdi + 8], rdx ; Set the firs digit
197
198 xor rax, rax ; Set the remaining digits to 0
199<% for (let i=1; i<n64; i++) { %>
200 mov [rdi + <%= (i+1)*8 %>], rax
201<% } %>
202 ret
203
204 ; edx is negative.
205rs2ln:
206
207 add rdx, [q] ; Set the firs digit
208 mov [rdi + 8], rdx ;
209
210 mov rdx, -1 ; all ones
211<% for (let i=1; i<n64; i++) { %>
212 mov rax, rdx ; Add to q
213 adc rax, [q + <%= i*8 %> ]
214 mov [rdi + <%= (i+1)*8 %>], rax
215<% } %>
216 ret
217
218l1:
219 mov rcx, [rdx]
220 bt rcx, 63
221 jc ll
222
223l1s2:
224 xor rdx, rdx
225 mov edx, ecx
226 bt rax, 62
227 jc lsM
228 jmp lsN
229
230s1l2:
231 mov rsi, rdx
232 xor rdx, rdx
233 mov edx, eax
234 bt rcx, 62
235 jc lsM
236 jmp lsN
237
238
239lsN:
240 mov byte [rdi + 3], 0xC0 ; set the result to montgomery
241 add rsi, 8
242 add rdi, 8
243 call mulSM
244 mov rdx, R3
245 call mulM
246 ret
247
248lsM:
249 mov byte [rdi + 3], 0x80 ; set the result to long normal
250 add rsi, 8
251 add rdi, 8
252 call mulSM
253 ret
254
255
256ll:
257
258 bt rax, 62
259 jc lml
260 bt rcx, 62
261 jc lnlm
262
263lnln:
264 mov byte [rdi + 3], 0xC0 ; set the result to long montgomery
265 add rsi, 8
266 add rdi, 8
267 add rdx, 8
268 call mulM
269 mov rdi, rsi
270 mov rdx, R3
271 call mulM
272 ret
273
274lml:
275 bt rcx, 62
276 jc lmlm
277
278lnlm:
279 mov byte [rdi + 3], 0x80 ; set the result to long normal
280 add rsi, 8
281 add rdi, 8
282 add rdx, 8
283 call mulM
284 ret
285
286lmlm:
287 mov byte [rdi + 3], 0xC0 ; set the result to long montgomery
288 add rsi, 8
289 add rdi, 8
290 add rdx, 8
291 call mulM
292 ret
293
294
295 section .data
296<%=name%>_q:
297 dd 0
298 dd 0x80000000
299q dq <%= constantElement(q) %>
300R3 dq <%= constantElement(bigInt.one.shiftLeft(n64*64*3).mod(q)) %>
301
302