circom/ports/c/buildasm/binops.asm.ejs
ports/c/buildasm/binops.asm.ejsRaw
1<% function binOpSubQIfBigger() { %>
2 <% const subQ = global.tmpLabel() %>
3 <% const done = global.tmpLabel() %>
4
5 ; Compare with q
6<% for (let i=0; i<n64; i++) { %>
7 mov rax, [rdi + <%= (n64-i)*8 %>]
8 cmp rax, [q + <%= (n64-i-1)*8 %>]
9 jc <%=done%> ; q is bigget so done.
10 jnz <%=subQ%> ; q is lower
11<% } %>
12 ; If equal substract q
13<%=subQ%>:
14<% for (let i=0; i<n64; i++) { %>
15 mov rax, [q + <%=i*8%>]
16 <%= i==0 ? "sub" : "sbb" %> [rdi + <%=i*8 + 8 %>], rax
17<% } %>
18<%=done%>:
19<% } %>
20
21
22<% function binOpS1S2(op) { %>
23 cmp r8d, 0
24 <% const s1s2_solveNeg = global.tmpLabel() %>
25 js <%=s1s2_solveNeg%>
26
27 cmp r9d, 0
28 js <%=s1s2_solveNeg%>
29 xor rdx, rdx ; both ops are positive so do the op and return
30 mov edx, r8d
31 <%=op%> edx, r9d
32 mov [rdi], rdx ; not necessary to adjust so just save and return
33 ret
34
35<%=s1s2_solveNeg%>:
36<%= global.setTypeDest("0x80"); %>
37<%= global.toLong_b() %>
38<%= global.toLong_a() %>
39<%= binOpL1L2(op) %>
40
41
42<% } %>
43
44<% function binOpS1L2(op) { %>
45 cmp r8d, 0
46 <% const s1l2_solveNeg = global.tmpLabel() %>
47 js <%=s1l2_solveNeg%>
48 movsx rax, r8d
49 <%=op%> rax, [rdx +8]
50 mov [rdi+8], rax
51<% for (let i=1; i<n64; i++) { %>
52 xor rax, rax
53 <%=op%> rax, [rdx + <%= (i*8)+8 %>]
54<% if (i== n64-1) { %>
55 and rax, [lboMask]
56<% } %>
57 mov [rdi + <%= (i*8)+8 %> ], rax
58<% } %>
59<% binOpSubQIfBigger() %>
60 ret
61
62<%=s1l2_solveNeg%>:
63<%= global.toLong_a() %>
64<%= global.setTypeDest("0x80"); %>
65<%= binOpL1L2(op) %>
66
67<% } %>
68
69<% function binOpL1S2(op) { %>
70 cmp r9d, 0
71 <% const l1s2_solveNeg = global.tmpLabel() %>
72 js <%=l1s2_solveNeg%>
73 movsx rax, r9d
74 <%=op%> rax, [rsi +8]
75 mov [rdi+8], rax
76<% for (let i=1; i<n64; i++) { %>
77 xor rax, rax
78 <%=op%> rax, [rsi + <%= (i*8)+8 %>];
79<% if (i== n64-1) { %>
80 and rax, [lboMask] ;
81<% } %>
82 mov [rdi + <%= (i*8)+8 %> ], rax;
83<% } %>
84<% binOpSubQIfBigger() %>
85 ret
86
87<%=l1s2_solveNeg%>:
88<%= global.toLong_b() %>
89<%= global.setTypeDest("0x80"); %>
90<%= binOpL1L2(op) %>
91
92<% } %>
93
94<% function binOpL1L2(op) { %>
95<% for (let i=0; i<n64; i++) { %>
96 mov rax, [rsi + <%= (i*8)+8 %>]
97 <%=op%> rax, [rdx + <%= (i*8)+8 %>]
98<% if (i== n64-1) { %>
99 and rax, [lboMask]
100<% } %>
101 mov [rdi + <%= (i*8)+8 %> ], rax
102<% } %>
103<% binOpSubQIfBigger() %>
104 ret
105<% } %>
106
107
108<% function binOp(op) { %>
109;;;;;;;;;;;;;;;;;;;;;;
110; b<%= op %>
111;;;;;;;;;;;;;;;;;;;;;;
112; Adds two elements of any kind
113; Params:
114; rsi <= Pointer to element 1
115; rdx <= Pointer to element 2
116; rdi <= Pointer to result
117; Modified Registers:
118; r8, r9, 10, r11, rax, rcx
119;;;;;;;;;;;;;;;;;;;;;;
120<%=name%>_b<%=op%>:
121 mov r8, [rsi]
122 mov r9, [rdx]
123 bt r8, 63 ; Check if is short first operand
124 jc <%=op%>_l1
125 bt r9, 63 ; Check if is short second operand
126 jc <%=op%>_s1l2
127
128<%=op%>_s1s2:
129<%= binOpS1S2(op) %>
130
131
132<%=op%>_l1:
133 bt r9, 63 ; Check if is short second operand
134 jc <%=op%>_l1l2
135
136
137<%=op%>_l1s2:
138 bt r8, 62 ; check if montgomery first
139 jc <%=op%>_l1ms2
140<%=op%>_l1ns2:
141<%= global.setTypeDest("0x80"); %>
142<%= binOpL1S2(op) %>
143
144<%=op%>_l1ms2:
145<%= global.setTypeDest("0x80"); %>
146 push r9 ; r9 is used in montgomery so we need to save it
147<%= global.fromMont_a() %>
148 pop r9
149<%= binOpL1S2(op) %>
150
151
152<%=op%>_s1l2:
153 bt r9, 62 ; check if montgomery first
154 jc <%=op%>_s1l2m
155<%=op%>_s1l2n:
156<%= global.setTypeDest("0x80"); %>
157<%= binOpS1L2(op) %>
158
159<%=op%>_s1l2m:
160<%= global.setTypeDest("0x80"); %>
161 push r8 ; r8 is used in montgomery so we need to save it
162<%= global.fromMont_b() %>
163 pop r8
164<%= binOpS1L2(op) %>
165
166
167<%=op%>_l1l2:
168 bt r8, 62 ; check if montgomery first
169 jc <%=op%>_l1ml2
170 bt r9, 62 ; check if montgomery first
171 jc <%=op%>_l1nl2m
172<%=op%>_l1nl2n:
173<%= global.setTypeDest("0x80"); %>
174<%= binOpL1L2(op) %>
175
176<%=op%>_l1nl2m:
177<%= global.setTypeDest("0x80"); %>
178<%= global.fromMont_b() %>
179<%= binOpL1L2(op) %>
180
181<%=op%>_l1ml2:
182 bt r9, 62 ; check if montgomery first
183 jc <%=op%>_l1ml2m
184<%=op%>_l1ml2n:
185<%= global.setTypeDest("0x80"); %>
186<%= global.fromMont_a() %>
187<%= binOpL1L2(op) %>
188
189<%=op%>_l1ml2m:
190<%= global.setTypeDest("0x80"); %>
191<%= global.fromMont_a() %>
192<%= global.fromMont_b() %>
193<%= binOpL1L2(op) %>
194<% } %>
195
196<%= binOp("and") %>
197<%= binOp("or") %>
198<%= binOp("xor") %>
199
200
201;;;;;;;;;;;;;;;;;;;;;;
202; bnot
203;;;;;;;;;;;;;;;;;;;;;;
204; Adds two elements of any kind
205; Params:
206; rsi <= Pointer to element 1
207; rdi <= Pointer to result
208; Modified Registers:
209; r8, r9, 10, r11, rax, rcx
210;;;;;;;;;;;;;;;;;;;;;;
211<%=name%>_bnot:
212 <%= global.setTypeDest("0x80"); %>
213
214 mov r8, [rsi]
215 bt r8, 63 ; Check if is long operand
216 jc bnot_l1
217bnot_s:
218 <%= global.toLong_a() %>
219 jmp bnot_l1n
220
221bnot_l1:
222 bt r8, 62 ; check if montgomery first
223 jnc bnot_l1n
224
225bnot_l1m:
226<%= global.fromMont_a() %>
227
228bnot_l1n:
229<% for (let i=0; i<n64; i++) { %>
230 mov rax, [rsi + <%= i*8 + 8 %>]
231 not rax
232<% if (i== n64-1) { %>
233 and rax, [lboMask]
234<% } %>
235 mov [rdi + <%= i*8 + 8 %>], rax
236<% } %>
237<% binOpSubQIfBigger() %>
238 ret
239
240