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