arnaucube
arnaucube/circomPublic Self-hosted repository
toInt and isTrue in assembly
Jordi Baylina jordi@baylina.cat
Thu, 23 Jan 2020 09:31:29 +0700
commit

20058a38d6b21362d314ffc7c8bcf1e78b1ebe18

parent

f6092e39442ad5b9c3110a25e90ff10ee9d3e5e8

M c/buildasm/copy.asm.ejs → c/buildasm/copy.asm.ejs

@@ -79,3 +79,55 @@ adc rax, [q + <%= i*8 %> ]

mov [rdi + <%= (i+1)*8 %>], rax <% } %> ret + +;;;;;;;;;;;;;;;;;;;;;; +; toInt +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= The value +;;;;;;;;;;;;;;;;;;;;;;; +<%=name%>_toInt: + mov rax, [rdi] + bt rax, 63 + jc <%=name%>_long + movsx rax, eax + ret + +<%=name%>_long: + mov rax, [rdi + 8] + mov rcx, rax + shr rcx, 31 + jnz <%=name%>_longNeg +<% for (let i=1; i< n64; i++) { %> + mov rcx, [rdi + <%= i*8+8 %>] + test rcx, rcx + jnz <%=name%>_longNeg +<% } %> + ret + +<%=name%>_longNeg: + mov rax, [rdi + 8] + sub rax, [q] + jnc <%=name%>_longErr +<% for (let i=1; i<n64; i++) { %> + mov rcx, [rdi + <%= i*8+8 %>] + sbb rcx, [q + <%= i*8 %>] + jnc <%=name%>_longErr +<% } %> + mov rcx, rax + sar rcx, 31 + add rcx, 1 + jnz <%=name%>_longErr + ret + +<%=name%>_longErr: + push rdi + mov rdi, 0 + call <%=name%>_fail + pop rdi + + +
M c/buildasm/fr.asm → c/buildasm/fr.asm

@@ -23,7 +23,10 @@ global Fr_lnot

global Fr_toNormal global Fr_toLongNormal global Fr_toMontgomery + global Fr_toInt + global Fr_isTrue global Fr_q + extern Fr_fail DEFAULT REL section .text

@@ -149,6 +152,74 @@ adc rax, [q + 24 ]

mov [rdi + 32], rax ret + +;;;;;;;;;;;;;;;;;;;;;; +; toInt +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= The value +;;;;;;;;;;;;;;;;;;;;;;; +Fr_toInt: + mov rax, [rdi] + bt rax, 63 + jc Fr_long + movsx rax, eax + ret + +Fr_long: + mov rax, [rdi + 8] + mov rcx, rax + shr rcx, 31 + jnz Fr_longNeg + + mov rcx, [rdi + 16] + test rcx, rcx + jnz Fr_longNeg + + mov rcx, [rdi + 24] + test rcx, rcx + jnz Fr_longNeg + + mov rcx, [rdi + 32] + test rcx, rcx + jnz Fr_longNeg + + ret + +Fr_longNeg: + mov rax, [rdi + 8] + sub rax, [q] + jnc Fr_longErr + + mov rcx, [rdi + 16] + sbb rcx, [q + 8] + jnc Fr_longErr + + mov rcx, [rdi + 24] + sbb rcx, [q + 16] + jnc Fr_longErr + + mov rcx, [rdi + 32] + sbb rcx, [q + 24] + jnc Fr_longErr + + mov rcx, rax + sar rcx, 31 + add rcx, 1 + jnz Fr_longErr + ret + +Fr_longErr: + push rdi + mov rdi, 0 + call Fr_fail + pop rdi + + +

@@ -1432,6 +1503,7 @@ mov r8, rsi ; save rsi

movsx rsi, eax call rawCopyS2L mov rsi, r8 ; recover rsi + ret

@@ -5697,6 +5769,62 @@ ret

lnot_retOne: mov qword [rdi], 1 ret + + +;;;;;;;;;;;;;;;;;;;;;; +; isTrue +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= 1 if true 0 if false +;;;;;;;;;;;;;;;;;;;;;;; +Fr_isTrue: + + + + + + + mov rax, [rdi] + bt rax, 63 + jc tmp_64 + + test eax, eax + jz retZero_66 + jmp retOne_65 + +tmp_64: + + mov rax, [rdi + 8] + test rax, rax + jnz retOne_65 + + mov rax, [rdi + 16] + test rax, rax + jnz retOne_65 + + mov rax, [rdi + 24] + test rax, rax + jnz retOne_65 + + mov rax, [rdi + 32] + test rax, rax + jnz retOne_65 + + +retZero_66: + mov qword rax, 0 + jmp done_67 + +retOne_65: + mov qword rax, 1 + +done_67: + + ret +
M c/buildasm/fr.asm.ejs → c/buildasm/fr.asm.ejs

@@ -23,7 +23,10 @@ global <%=name%>_lnot

global <%=name%>_toNormal global <%=name%>_toLongNormal global <%=name%>_toMontgomery + global <%=name%>_toInt + global <%=name%>_isTrue global <%=name%>_q + extern <%=name%>_fail DEFAULT REL section .text
M c/buildasm/fr.c → c/buildasm/fr.c

@@ -179,32 +179,7 @@ Fr_inv(&tmp, b);

Fr_mul(r, a, &tmp); } -int Fr_isTrue(PFrElement pE) { - if (!(pE->type & Fr_LONG)) return pE->shortVal != 0; - for (int i=0; i< Fr_N64; i++) { - if (pE->longVal[i]) return 1; - } - return 0; -} - -int Fr_toInt(PFrElement pE) { - Fr_toNormal(pE); - if (!(pE->type & Fr_LONG)) { - return pE->shortVal; - } else { - mpz_t ma; - mpz_init(ma); - Fr_toMpz(ma, pE); - if (mpz_fits_sint_p(ma)) { - return mpz_get_si(ma); - } - - mpz_sub(ma, ma, q); - if (mpz_fits_sint_p(ma)) { - return mpz_get_si(ma); - } else { - assert(false); - } - } +void Fr_fail() { + assert(false); }
M c/buildasm/fr.c.ejs → c/buildasm/fr.c.ejs

@@ -179,32 +179,7 @@ <%=name%>_inv(&tmp, b);

<%=name%>_mul(r, a, &tmp); } -int <%=name%>_isTrue(P<%=name%>Element pE) { - if (!(pE->type & <%=name%>_LONG)) return pE->shortVal != 0; - for (int i=0; i< <%=name%>_N64; i++) { - if (pE->longVal[i]) return 1; - } - return 0; -} - -int <%=name%>_toInt(P<%=name%>Element pE) { - Fr_toNormal(pE); - if (!(pE->type & <%=name%>_LONG)) { - return pE->shortVal; - } else { - mpz_t ma; - mpz_init(ma); - <%=name%>_toMpz(ma, pE); - if (mpz_fits_sint_p(ma)) { - return mpz_get_si(ma); - } - - mpz_sub(ma, ma, q); - if (mpz_fits_sint_p(ma)) { - return mpz_get_si(ma); - } else { - assert(false); - } - } +void <%=name%>_fail() { + assert(false); }
M c/buildasm/fr.h → c/buildasm/fr.h

@@ -36,6 +36,16 @@ extern "C" void Fr_lnot(PFrElement r, PFrElement a);

extern "C" void Fr_toNormal(PFrElement pE); extern "C" void Fr_toLongNormal(PFrElement pE); extern "C" void Fr_toMontgomery(PFrElement pE); + +extern "C" int Fr_isTrue(PFrElement pE); +extern "C" int Fr_toInt(PFrElement pE); + +extern "C" void Fr_fail(); + +extern FrElement Fr_q; + +// Pending functions to convert + void Fr_str2element(PFrElement pE, char const*s); char *Fr_element2str(PFrElement pE); void Fr_idiv(PFrElement r, PFrElement a, PFrElement b);

@@ -46,12 +56,9 @@ void Fr_shl(PFrElement r, PFrElement a, PFrElement b);

void Fr_shr(PFrElement r, PFrElement a, PFrElement b); void Fr_pow(PFrElement r, PFrElement a, PFrElement b); -int Fr_isTrue(PFrElement pE); -int Fr_toInt(PFrElement pE); void Fr_init(); -extern FrElement Fr_q; #endif // __FR_H
M c/buildasm/fr.h.ejs → c/buildasm/fr.h.ejs

@@ -36,6 +36,16 @@ extern "C" void <%=name%>_lnot(P<%=name%>Element r, P<%=name%>Element a);

extern "C" void <%=name%>_toNormal(P<%=name%>Element pE); extern "C" void <%=name%>_toLongNormal(P<%=name%>Element pE); extern "C" void <%=name%>_toMontgomery(P<%=name%>Element pE); + +extern "C" int <%=name%>_isTrue(P<%=name%>Element pE); +extern "C" int <%=name%>_toInt(P<%=name%>Element pE); + +extern "C" void <%=name%>_fail(); + +extern <%=name%>Element <%=name%>_q; + +// Pending functions to convert + void <%=name%>_str2element(P<%=name%>Element pE, char const*s); char *<%=name%>_element2str(P<%=name%>Element pE); void <%=name%>_idiv(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b);

@@ -46,12 +56,9 @@ void <%=name%>_shl(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b);

void <%=name%>_shr(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b); void <%=name%>_pow(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b); -int <%=name%>_isTrue(P<%=name%>Element pE); -int <%=name%>_toInt(P<%=name%>Element pE); void <%=name%>_init(); -extern <%=name%>Element <%=name%>_q; #endif // __<%=name.toUpperCase()%>_H
M c/buildasm/logicalops.asm.ejs → c/buildasm/logicalops.asm.ejs

@@ -80,3 +80,18 @@ mov qword [rdi], 1

ret +;;;;;;;;;;;;;;;;;;;;;; +; isTrue +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= 1 if true 0 if false +;;;;;;;;;;;;;;;;;;;;;;; +<%=name%>_isTrue: + <%= isTrue("rax", "rdi") %> + ret + + +
M c/buildasm/main.c → c/buildasm/main.c

@@ -1,13 +1,15 @@

#include <stdio.h> #include <stdlib.h> +#include <assert.h> #include "fr.h" int main() { - + Fr_init(); +/* FrElement a = { 0, Fr_LONGMONTGOMERY, {1,1,1,1}}; FrElement b = { 0, Fr_LONGMONTGOMERY, {2,2,2,2}}; -/* + FrElement a={0x43e1f593f0000000ULL,0x2833e84879b97091ULL,0xb85045b68181585dULL,0x30644e72e131a029ULL}; FrElement b = {3,0,0,0};

@@ -24,6 +26,7 @@

Fr_mul(&c,&a, &b); */ +/* FrElement a1[10]; FrElement a2[10]; for (int i=0; i<10; i++) {

@@ -43,6 +46,19 @@ printf("%s\n%s\n\n", c1, c2);

free(c1); free(c2); } +*/ + + int tests[7] = { 0, 1, 2, -1, -2, 0x7FFFFFFF, (int)0x80000000}; + for (int i=0; i<7;i++) { + FrElement a = { tests[i], Fr_SHORT, {0,0,0,0}}; + Fr_toLongNormal(&a); + int b = Fr_toInt(&a); + int c = Fr_isTrue(&a); + printf("%d, %d, %d\n", tests[i], b, c); + } + + FrElement err = { 0, Fr_LONGMONTGOMERY, {1,1,1,1}}; + Fr_toInt(&err); // printf("%llu, %llu, %llu, %llu\n", c.longVal[0], c.longVal[1], c.longVal[2], c.longVal[3]); }
M c/buildasm/montgomery.asm.ejs → c/buildasm/montgomery.asm.ejs

@@ -338,4 +338,5 @@ mov r8, rsi ; save rsi

movsx rsi, eax call rawCopyS2L mov rsi, r8 ; recover rsi + ret
M c/buildasm/tester.cpp → c/buildasm/tester.cpp

@@ -139,6 +139,7 @@ }

int main(void) { + Fr_init(); fillMap(); std::string line; int i=0;
M test/fieldasm.js → test/fieldasm.js

@@ -13,7 +13,6 @@ const mnt6753r = new bigInt("41898490967918953402344214791240637128170709919953949071783502921025352812571106773058893763790338921418070971888253786114353726529584385201591605722013126468931404347949840543007986327743462853720628051692141265303114721689601");

describe("field asm test", function () { this.timeout(1000000000); -/* it("bn128r add", async () => { const tv = buildTestVector2(bn128r, "add"); await tester(bn128r, tv);

@@ -255,7 +254,6 @@ it("mnt6753q div", async () => {

const tv = buildTestVector2(mnt6753q, "div"); await tester(mnt6753q, tv); }); -*/ it("bn128r square", async () => { const tv = buildTestVector1(bn128r, "square"); await tester(bn128r, tv);