github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-317/fp/element_mul_amd64.s (about) 1 // +build !purego 2 3 // Copyright 2020 ConsenSys Software Inc. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #include "textflag.h" 18 #include "funcdata.h" 19 20 // modulus q 21 DATA q<>+0(SB)/8, $0x8d512e565dab2aab 22 DATA q<>+8(SB)/8, $0xd6f339e43424bf7e 23 DATA q<>+16(SB)/8, $0x169a61e684c73446 24 DATA q<>+24(SB)/8, $0xf28fc5a0b7f9d039 25 DATA q<>+32(SB)/8, $0x1058ca226f60892c 26 GLOBL q<>(SB), (RODATA+NOPTR), $40 27 28 // qInv0 q'[0] 29 DATA qInv0<>(SB)/8, $0x55b5e0028b047ffd 30 GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 31 32 #define REDUCE(ra0, ra1, ra2, ra3, ra4, rb0, rb1, rb2, rb3, rb4) \ 33 MOVQ ra0, rb0; \ 34 SUBQ q<>(SB), ra0; \ 35 MOVQ ra1, rb1; \ 36 SBBQ q<>+8(SB), ra1; \ 37 MOVQ ra2, rb2; \ 38 SBBQ q<>+16(SB), ra2; \ 39 MOVQ ra3, rb3; \ 40 SBBQ q<>+24(SB), ra3; \ 41 MOVQ ra4, rb4; \ 42 SBBQ q<>+32(SB), ra4; \ 43 CMOVQCS rb0, ra0; \ 44 CMOVQCS rb1, ra1; \ 45 CMOVQCS rb2, ra2; \ 46 CMOVQCS rb3, ra3; \ 47 CMOVQCS rb4, ra4; \ 48 49 // mul(res, x, y *Element) 50 TEXT ·mul(SB), $24-24 51 52 // the algorithm is described in the Element.Mul declaration (.go) 53 // however, to benefit from the ADCX and ADOX carry chains 54 // we split the inner loops in 2: 55 // for i=0 to N-1 56 // for j=0 to N-1 57 // (A,t[j]) := t[j] + x[j]*y[i] + A 58 // m := t[0]*q'[0] mod W 59 // C,_ := t[0] + m*q[0] 60 // for j=1 to N-1 61 // (C,t[j-1]) := t[j] + m*q[j] + C 62 // t[N-1] = C + A 63 64 NO_LOCAL_POINTERS 65 CMPB ·supportAdx(SB), $1 66 JNE l1 67 MOVQ x+8(FP), DI 68 69 // x[0] -> R9 70 // x[1] -> R10 71 // x[2] -> R11 72 MOVQ 0(DI), R9 73 MOVQ 8(DI), R10 74 MOVQ 16(DI), R11 75 MOVQ y+16(FP), R12 76 77 // A -> BP 78 // t[0] -> R14 79 // t[1] -> R13 80 // t[2] -> CX 81 // t[3] -> BX 82 // t[4] -> SI 83 // clear the flags 84 XORQ AX, AX 85 MOVQ 0(R12), DX 86 87 // (A,t[0]) := x[0]*y[0] + A 88 MULXQ R9, R14, R13 89 90 // (A,t[1]) := x[1]*y[0] + A 91 MULXQ R10, AX, CX 92 ADOXQ AX, R13 93 94 // (A,t[2]) := x[2]*y[0] + A 95 MULXQ R11, AX, BX 96 ADOXQ AX, CX 97 98 // (A,t[3]) := x[3]*y[0] + A 99 MULXQ 24(DI), AX, SI 100 ADOXQ AX, BX 101 102 // (A,t[4]) := x[4]*y[0] + A 103 MULXQ 32(DI), AX, BP 104 ADOXQ AX, SI 105 106 // A += carries from ADCXQ and ADOXQ 107 MOVQ $0, AX 108 ADOXQ AX, BP 109 110 // m := t[0]*q'[0] mod W 111 MOVQ qInv0<>(SB), DX 112 IMULQ R14, DX 113 114 // clear the flags 115 XORQ AX, AX 116 117 // C,_ := t[0] + m*q[0] 118 MULXQ q<>+0(SB), AX, R8 119 ADCXQ R14, AX 120 MOVQ R8, R14 121 122 // (C,t[0]) := t[1] + m*q[1] + C 123 ADCXQ R13, R14 124 MULXQ q<>+8(SB), AX, R13 125 ADOXQ AX, R14 126 127 // (C,t[1]) := t[2] + m*q[2] + C 128 ADCXQ CX, R13 129 MULXQ q<>+16(SB), AX, CX 130 ADOXQ AX, R13 131 132 // (C,t[2]) := t[3] + m*q[3] + C 133 ADCXQ BX, CX 134 MULXQ q<>+24(SB), AX, BX 135 ADOXQ AX, CX 136 137 // (C,t[3]) := t[4] + m*q[4] + C 138 ADCXQ SI, BX 139 MULXQ q<>+32(SB), AX, SI 140 ADOXQ AX, BX 141 142 // t[4] = C + A 143 MOVQ $0, AX 144 ADCXQ AX, SI 145 ADOXQ BP, SI 146 147 // clear the flags 148 XORQ AX, AX 149 MOVQ 8(R12), DX 150 151 // (A,t[0]) := t[0] + x[0]*y[1] + A 152 MULXQ R9, AX, BP 153 ADOXQ AX, R14 154 155 // (A,t[1]) := t[1] + x[1]*y[1] + A 156 ADCXQ BP, R13 157 MULXQ R10, AX, BP 158 ADOXQ AX, R13 159 160 // (A,t[2]) := t[2] + x[2]*y[1] + A 161 ADCXQ BP, CX 162 MULXQ R11, AX, BP 163 ADOXQ AX, CX 164 165 // (A,t[3]) := t[3] + x[3]*y[1] + A 166 ADCXQ BP, BX 167 MULXQ 24(DI), AX, BP 168 ADOXQ AX, BX 169 170 // (A,t[4]) := t[4] + x[4]*y[1] + A 171 ADCXQ BP, SI 172 MULXQ 32(DI), AX, BP 173 ADOXQ AX, SI 174 175 // A += carries from ADCXQ and ADOXQ 176 MOVQ $0, AX 177 ADCXQ AX, BP 178 ADOXQ AX, BP 179 180 // m := t[0]*q'[0] mod W 181 MOVQ qInv0<>(SB), DX 182 IMULQ R14, DX 183 184 // clear the flags 185 XORQ AX, AX 186 187 // C,_ := t[0] + m*q[0] 188 MULXQ q<>+0(SB), AX, R8 189 ADCXQ R14, AX 190 MOVQ R8, R14 191 192 // (C,t[0]) := t[1] + m*q[1] + C 193 ADCXQ R13, R14 194 MULXQ q<>+8(SB), AX, R13 195 ADOXQ AX, R14 196 197 // (C,t[1]) := t[2] + m*q[2] + C 198 ADCXQ CX, R13 199 MULXQ q<>+16(SB), AX, CX 200 ADOXQ AX, R13 201 202 // (C,t[2]) := t[3] + m*q[3] + C 203 ADCXQ BX, CX 204 MULXQ q<>+24(SB), AX, BX 205 ADOXQ AX, CX 206 207 // (C,t[3]) := t[4] + m*q[4] + C 208 ADCXQ SI, BX 209 MULXQ q<>+32(SB), AX, SI 210 ADOXQ AX, BX 211 212 // t[4] = C + A 213 MOVQ $0, AX 214 ADCXQ AX, SI 215 ADOXQ BP, SI 216 217 // clear the flags 218 XORQ AX, AX 219 MOVQ 16(R12), DX 220 221 // (A,t[0]) := t[0] + x[0]*y[2] + A 222 MULXQ R9, AX, BP 223 ADOXQ AX, R14 224 225 // (A,t[1]) := t[1] + x[1]*y[2] + A 226 ADCXQ BP, R13 227 MULXQ R10, AX, BP 228 ADOXQ AX, R13 229 230 // (A,t[2]) := t[2] + x[2]*y[2] + A 231 ADCXQ BP, CX 232 MULXQ R11, AX, BP 233 ADOXQ AX, CX 234 235 // (A,t[3]) := t[3] + x[3]*y[2] + A 236 ADCXQ BP, BX 237 MULXQ 24(DI), AX, BP 238 ADOXQ AX, BX 239 240 // (A,t[4]) := t[4] + x[4]*y[2] + A 241 ADCXQ BP, SI 242 MULXQ 32(DI), AX, BP 243 ADOXQ AX, SI 244 245 // A += carries from ADCXQ and ADOXQ 246 MOVQ $0, AX 247 ADCXQ AX, BP 248 ADOXQ AX, BP 249 250 // m := t[0]*q'[0] mod W 251 MOVQ qInv0<>(SB), DX 252 IMULQ R14, DX 253 254 // clear the flags 255 XORQ AX, AX 256 257 // C,_ := t[0] + m*q[0] 258 MULXQ q<>+0(SB), AX, R8 259 ADCXQ R14, AX 260 MOVQ R8, R14 261 262 // (C,t[0]) := t[1] + m*q[1] + C 263 ADCXQ R13, R14 264 MULXQ q<>+8(SB), AX, R13 265 ADOXQ AX, R14 266 267 // (C,t[1]) := t[2] + m*q[2] + C 268 ADCXQ CX, R13 269 MULXQ q<>+16(SB), AX, CX 270 ADOXQ AX, R13 271 272 // (C,t[2]) := t[3] + m*q[3] + C 273 ADCXQ BX, CX 274 MULXQ q<>+24(SB), AX, BX 275 ADOXQ AX, CX 276 277 // (C,t[3]) := t[4] + m*q[4] + C 278 ADCXQ SI, BX 279 MULXQ q<>+32(SB), AX, SI 280 ADOXQ AX, BX 281 282 // t[4] = C + A 283 MOVQ $0, AX 284 ADCXQ AX, SI 285 ADOXQ BP, SI 286 287 // clear the flags 288 XORQ AX, AX 289 MOVQ 24(R12), DX 290 291 // (A,t[0]) := t[0] + x[0]*y[3] + A 292 MULXQ R9, AX, BP 293 ADOXQ AX, R14 294 295 // (A,t[1]) := t[1] + x[1]*y[3] + A 296 ADCXQ BP, R13 297 MULXQ R10, AX, BP 298 ADOXQ AX, R13 299 300 // (A,t[2]) := t[2] + x[2]*y[3] + A 301 ADCXQ BP, CX 302 MULXQ R11, AX, BP 303 ADOXQ AX, CX 304 305 // (A,t[3]) := t[3] + x[3]*y[3] + A 306 ADCXQ BP, BX 307 MULXQ 24(DI), AX, BP 308 ADOXQ AX, BX 309 310 // (A,t[4]) := t[4] + x[4]*y[3] + A 311 ADCXQ BP, SI 312 MULXQ 32(DI), AX, BP 313 ADOXQ AX, SI 314 315 // A += carries from ADCXQ and ADOXQ 316 MOVQ $0, AX 317 ADCXQ AX, BP 318 ADOXQ AX, BP 319 320 // m := t[0]*q'[0] mod W 321 MOVQ qInv0<>(SB), DX 322 IMULQ R14, DX 323 324 // clear the flags 325 XORQ AX, AX 326 327 // C,_ := t[0] + m*q[0] 328 MULXQ q<>+0(SB), AX, R8 329 ADCXQ R14, AX 330 MOVQ R8, R14 331 332 // (C,t[0]) := t[1] + m*q[1] + C 333 ADCXQ R13, R14 334 MULXQ q<>+8(SB), AX, R13 335 ADOXQ AX, R14 336 337 // (C,t[1]) := t[2] + m*q[2] + C 338 ADCXQ CX, R13 339 MULXQ q<>+16(SB), AX, CX 340 ADOXQ AX, R13 341 342 // (C,t[2]) := t[3] + m*q[3] + C 343 ADCXQ BX, CX 344 MULXQ q<>+24(SB), AX, BX 345 ADOXQ AX, CX 346 347 // (C,t[3]) := t[4] + m*q[4] + C 348 ADCXQ SI, BX 349 MULXQ q<>+32(SB), AX, SI 350 ADOXQ AX, BX 351 352 // t[4] = C + A 353 MOVQ $0, AX 354 ADCXQ AX, SI 355 ADOXQ BP, SI 356 357 // clear the flags 358 XORQ AX, AX 359 MOVQ 32(R12), DX 360 361 // (A,t[0]) := t[0] + x[0]*y[4] + A 362 MULXQ R9, AX, BP 363 ADOXQ AX, R14 364 365 // (A,t[1]) := t[1] + x[1]*y[4] + A 366 ADCXQ BP, R13 367 MULXQ R10, AX, BP 368 ADOXQ AX, R13 369 370 // (A,t[2]) := t[2] + x[2]*y[4] + A 371 ADCXQ BP, CX 372 MULXQ R11, AX, BP 373 ADOXQ AX, CX 374 375 // (A,t[3]) := t[3] + x[3]*y[4] + A 376 ADCXQ BP, BX 377 MULXQ 24(DI), AX, BP 378 ADOXQ AX, BX 379 380 // (A,t[4]) := t[4] + x[4]*y[4] + A 381 ADCXQ BP, SI 382 MULXQ 32(DI), AX, BP 383 ADOXQ AX, SI 384 385 // A += carries from ADCXQ and ADOXQ 386 MOVQ $0, AX 387 ADCXQ AX, BP 388 ADOXQ AX, BP 389 390 // m := t[0]*q'[0] mod W 391 MOVQ qInv0<>(SB), DX 392 IMULQ R14, DX 393 394 // clear the flags 395 XORQ AX, AX 396 397 // C,_ := t[0] + m*q[0] 398 MULXQ q<>+0(SB), AX, R8 399 ADCXQ R14, AX 400 MOVQ R8, R14 401 402 // (C,t[0]) := t[1] + m*q[1] + C 403 ADCXQ R13, R14 404 MULXQ q<>+8(SB), AX, R13 405 ADOXQ AX, R14 406 407 // (C,t[1]) := t[2] + m*q[2] + C 408 ADCXQ CX, R13 409 MULXQ q<>+16(SB), AX, CX 410 ADOXQ AX, R13 411 412 // (C,t[2]) := t[3] + m*q[3] + C 413 ADCXQ BX, CX 414 MULXQ q<>+24(SB), AX, BX 415 ADOXQ AX, CX 416 417 // (C,t[3]) := t[4] + m*q[4] + C 418 ADCXQ SI, BX 419 MULXQ q<>+32(SB), AX, SI 420 ADOXQ AX, BX 421 422 // t[4] = C + A 423 MOVQ $0, AX 424 ADCXQ AX, SI 425 ADOXQ BP, SI 426 427 // reduce element(R14,R13,CX,BX,SI) using temp registers (R8,DI,R12,R9,R10) 428 REDUCE(R14,R13,CX,BX,SI,R8,DI,R12,R9,R10) 429 430 MOVQ res+0(FP), AX 431 MOVQ R14, 0(AX) 432 MOVQ R13, 8(AX) 433 MOVQ CX, 16(AX) 434 MOVQ BX, 24(AX) 435 MOVQ SI, 32(AX) 436 RET 437 438 l1: 439 MOVQ res+0(FP), AX 440 MOVQ AX, (SP) 441 MOVQ x+8(FP), AX 442 MOVQ AX, 8(SP) 443 MOVQ y+16(FP), AX 444 MOVQ AX, 16(SP) 445 CALL ·_mulGeneric(SB) 446 RET 447 448 TEXT ·fromMont(SB), $8-8 449 NO_LOCAL_POINTERS 450 451 // the algorithm is described here 452 // https://hackmd.io/@gnark/modular_multiplication 453 // when y = 1 we have: 454 // for i=0 to N-1 455 // t[i] = x[i] 456 // for i=0 to N-1 457 // m := t[0]*q'[0] mod W 458 // C,_ := t[0] + m*q[0] 459 // for j=1 to N-1 460 // (C,t[j-1]) := t[j] + m*q[j] + C 461 // t[N-1] = C 462 CMPB ·supportAdx(SB), $1 463 JNE l2 464 MOVQ res+0(FP), DX 465 MOVQ 0(DX), R14 466 MOVQ 8(DX), R13 467 MOVQ 16(DX), CX 468 MOVQ 24(DX), BX 469 MOVQ 32(DX), SI 470 XORQ DX, DX 471 472 // m := t[0]*q'[0] mod W 473 MOVQ qInv0<>(SB), DX 474 IMULQ R14, DX 475 XORQ AX, AX 476 477 // C,_ := t[0] + m*q[0] 478 MULXQ q<>+0(SB), AX, BP 479 ADCXQ R14, AX 480 MOVQ BP, R14 481 482 // (C,t[0]) := t[1] + m*q[1] + C 483 ADCXQ R13, R14 484 MULXQ q<>+8(SB), AX, R13 485 ADOXQ AX, R14 486 487 // (C,t[1]) := t[2] + m*q[2] + C 488 ADCXQ CX, R13 489 MULXQ q<>+16(SB), AX, CX 490 ADOXQ AX, R13 491 492 // (C,t[2]) := t[3] + m*q[3] + C 493 ADCXQ BX, CX 494 MULXQ q<>+24(SB), AX, BX 495 ADOXQ AX, CX 496 497 // (C,t[3]) := t[4] + m*q[4] + C 498 ADCXQ SI, BX 499 MULXQ q<>+32(SB), AX, SI 500 ADOXQ AX, BX 501 MOVQ $0, AX 502 ADCXQ AX, SI 503 ADOXQ AX, SI 504 XORQ DX, DX 505 506 // m := t[0]*q'[0] mod W 507 MOVQ qInv0<>(SB), DX 508 IMULQ R14, DX 509 XORQ AX, AX 510 511 // C,_ := t[0] + m*q[0] 512 MULXQ q<>+0(SB), AX, BP 513 ADCXQ R14, AX 514 MOVQ BP, R14 515 516 // (C,t[0]) := t[1] + m*q[1] + C 517 ADCXQ R13, R14 518 MULXQ q<>+8(SB), AX, R13 519 ADOXQ AX, R14 520 521 // (C,t[1]) := t[2] + m*q[2] + C 522 ADCXQ CX, R13 523 MULXQ q<>+16(SB), AX, CX 524 ADOXQ AX, R13 525 526 // (C,t[2]) := t[3] + m*q[3] + C 527 ADCXQ BX, CX 528 MULXQ q<>+24(SB), AX, BX 529 ADOXQ AX, CX 530 531 // (C,t[3]) := t[4] + m*q[4] + C 532 ADCXQ SI, BX 533 MULXQ q<>+32(SB), AX, SI 534 ADOXQ AX, BX 535 MOVQ $0, AX 536 ADCXQ AX, SI 537 ADOXQ AX, SI 538 XORQ DX, DX 539 540 // m := t[0]*q'[0] mod W 541 MOVQ qInv0<>(SB), DX 542 IMULQ R14, DX 543 XORQ AX, AX 544 545 // C,_ := t[0] + m*q[0] 546 MULXQ q<>+0(SB), AX, BP 547 ADCXQ R14, AX 548 MOVQ BP, R14 549 550 // (C,t[0]) := t[1] + m*q[1] + C 551 ADCXQ R13, R14 552 MULXQ q<>+8(SB), AX, R13 553 ADOXQ AX, R14 554 555 // (C,t[1]) := t[2] + m*q[2] + C 556 ADCXQ CX, R13 557 MULXQ q<>+16(SB), AX, CX 558 ADOXQ AX, R13 559 560 // (C,t[2]) := t[3] + m*q[3] + C 561 ADCXQ BX, CX 562 MULXQ q<>+24(SB), AX, BX 563 ADOXQ AX, CX 564 565 // (C,t[3]) := t[4] + m*q[4] + C 566 ADCXQ SI, BX 567 MULXQ q<>+32(SB), AX, SI 568 ADOXQ AX, BX 569 MOVQ $0, AX 570 ADCXQ AX, SI 571 ADOXQ AX, SI 572 XORQ DX, DX 573 574 // m := t[0]*q'[0] mod W 575 MOVQ qInv0<>(SB), DX 576 IMULQ R14, DX 577 XORQ AX, AX 578 579 // C,_ := t[0] + m*q[0] 580 MULXQ q<>+0(SB), AX, BP 581 ADCXQ R14, AX 582 MOVQ BP, R14 583 584 // (C,t[0]) := t[1] + m*q[1] + C 585 ADCXQ R13, R14 586 MULXQ q<>+8(SB), AX, R13 587 ADOXQ AX, R14 588 589 // (C,t[1]) := t[2] + m*q[2] + C 590 ADCXQ CX, R13 591 MULXQ q<>+16(SB), AX, CX 592 ADOXQ AX, R13 593 594 // (C,t[2]) := t[3] + m*q[3] + C 595 ADCXQ BX, CX 596 MULXQ q<>+24(SB), AX, BX 597 ADOXQ AX, CX 598 599 // (C,t[3]) := t[4] + m*q[4] + C 600 ADCXQ SI, BX 601 MULXQ q<>+32(SB), AX, SI 602 ADOXQ AX, BX 603 MOVQ $0, AX 604 ADCXQ AX, SI 605 ADOXQ AX, SI 606 XORQ DX, DX 607 608 // m := t[0]*q'[0] mod W 609 MOVQ qInv0<>(SB), DX 610 IMULQ R14, DX 611 XORQ AX, AX 612 613 // C,_ := t[0] + m*q[0] 614 MULXQ q<>+0(SB), AX, BP 615 ADCXQ R14, AX 616 MOVQ BP, R14 617 618 // (C,t[0]) := t[1] + m*q[1] + C 619 ADCXQ R13, R14 620 MULXQ q<>+8(SB), AX, R13 621 ADOXQ AX, R14 622 623 // (C,t[1]) := t[2] + m*q[2] + C 624 ADCXQ CX, R13 625 MULXQ q<>+16(SB), AX, CX 626 ADOXQ AX, R13 627 628 // (C,t[2]) := t[3] + m*q[3] + C 629 ADCXQ BX, CX 630 MULXQ q<>+24(SB), AX, BX 631 ADOXQ AX, CX 632 633 // (C,t[3]) := t[4] + m*q[4] + C 634 ADCXQ SI, BX 635 MULXQ q<>+32(SB), AX, SI 636 ADOXQ AX, BX 637 MOVQ $0, AX 638 ADCXQ AX, SI 639 ADOXQ AX, SI 640 641 // reduce element(R14,R13,CX,BX,SI) using temp registers (DI,R8,R9,R10,R11) 642 REDUCE(R14,R13,CX,BX,SI,DI,R8,R9,R10,R11) 643 644 MOVQ res+0(FP), AX 645 MOVQ R14, 0(AX) 646 MOVQ R13, 8(AX) 647 MOVQ CX, 16(AX) 648 MOVQ BX, 24(AX) 649 MOVQ SI, 32(AX) 650 RET 651 652 l2: 653 MOVQ res+0(FP), AX 654 MOVQ AX, (SP) 655 CALL ·_fromMontGeneric(SB) 656 RET