arnaucube
arnaucube/circomPublic Self-hosted repository
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