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