3 // Copyright 2018 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
11 // ----------------------- //
12 // bits.LeadingZeros //
13 // ----------------------- //
15 func LeadingZeros(n uint) int {
16 // amd64/v1,amd64/v2:"BSRQ"
17 // amd64/v3:"LZCNTQ", -"BSRQ"
19 // arm:"CLZ" arm64:"CLZ"
23 return bits.LeadingZeros(n)
26 func LeadingZeros64(n uint64) int {
27 // amd64/v1,amd64/v2:"BSRQ"
28 // amd64/v3:"LZCNTQ", -"BSRQ"
30 // arm:"CLZ" arm64:"CLZ"
34 return bits.LeadingZeros64(n)
37 func LeadingZeros32(n uint32) int {
38 // amd64/v1,amd64/v2:"BSRQ","LEAQ",-"CMOVQEQ"
39 // amd64/v3: "LZCNTL",- "BSRL"
41 // arm:"CLZ" arm64:"CLZW"
45 return bits.LeadingZeros32(n)
48 func LeadingZeros16(n uint16) int {
49 // amd64/v1,amd64/v2:"BSRL","LEAL",-"CMOVQEQ"
50 // amd64/v3: "LZCNTL",- "BSRL"
52 // arm:"CLZ" arm64:"CLZ"
56 return bits.LeadingZeros16(n)
59 func LeadingZeros8(n uint8) int {
60 // amd64/v1,amd64/v2:"BSRL","LEAL",-"CMOVQEQ"
61 // amd64/v3: "LZCNTL",- "BSRL"
63 // arm:"CLZ" arm64:"CLZ"
67 return bits.LeadingZeros8(n)
74 func Len(n uint) int {
75 // amd64/v1,amd64/v2:"BSRQ"
78 // arm:"CLZ" arm64:"CLZ"
81 // ppc64x:"SUBC","CNTLZD"
85 func Len64(n uint64) int {
86 // amd64/v1,amd64/v2:"BSRQ"
89 // arm:"CLZ" arm64:"CLZ"
92 // ppc64x:"SUBC","CNTLZD"
96 func SubFromLen64(n uint64) int {
97 // ppc64x:"CNTLZD",-"SUBC"
98 return 64 - bits.Len64(n)
101 func Len32(n uint32) int {
102 // amd64/v1,amd64/v2:"BSRQ","LEAQ",-"CMOVQEQ"
103 // amd64/v3: "LZCNTL"
105 // arm:"CLZ" arm64:"CLZ"
112 func Len16(n uint16) int {
113 // amd64/v1,amd64/v2:"BSRL","LEAL",-"CMOVQEQ"
114 // amd64/v3: "LZCNTL"
116 // arm:"CLZ" arm64:"CLZ"
119 // ppc64x:"SUBC","CNTLZD"
123 func Len8(n uint8) int {
124 // amd64/v1,amd64/v2:"BSRL","LEAL",-"CMOVQEQ"
125 // amd64/v3: "LZCNTL"
127 // arm:"CLZ" arm64:"CLZ"
130 // ppc64x:"SUBC","CNTLZD"
134 // -------------------- //
136 // -------------------- //
138 // TODO(register args) Restore a m d 6 4 / v 1 :.*x86HasPOPCNT when only one ABI is tested.
139 func OnesCount(n uint) int {
140 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
142 // arm64:"VCNT","VUADDLV"
146 return bits.OnesCount(n)
149 func OnesCount64(n uint64) int {
150 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
152 // arm64:"VCNT","VUADDLV"
156 return bits.OnesCount64(n)
159 func OnesCount32(n uint32) int {
160 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
162 // arm64:"VCNT","VUADDLV"
166 return bits.OnesCount32(n)
169 func OnesCount16(n uint16) int {
170 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
172 // arm64:"VCNT","VUADDLV"
176 return bits.OnesCount16(n)
179 func OnesCount8(n uint8) int {
183 return bits.OnesCount8(n)
186 // ----------------------- //
187 // bits.ReverseBytes //
188 // ----------------------- //
190 func ReverseBytes(n uint) uint {
195 return bits.ReverseBytes(n)
198 func ReverseBytes64(n uint64) uint64 {
203 // ppc64x/power10: "BRD"
204 return bits.ReverseBytes64(n)
207 func ReverseBytes32(n uint32) uint32 {
212 // ppc64x/power10: "BRW"
213 return bits.ReverseBytes32(n)
216 func ReverseBytes16(n uint16) uint16 {
218 // arm64:"REV16W",-"UBFX",-"ORR"
219 // arm/5:"SLL","SRL","ORR"
222 // ppc64x/power10: "BRH"
223 return bits.ReverseBytes16(n)
226 // --------------------- //
227 // bits.RotateLeft //
228 // --------------------- //
230 func RotateLeft64(n uint64) uint64 {
234 // s390x:"RISBGZ\t[$]0, [$]63, [$]37, "
236 return bits.RotateLeft64(n, 37)
239 func RotateLeft32(n uint32) uint32 {
240 // amd64:"ROLL" 386:"ROLL"
241 // arm:`MOVW\tR[0-9]+@>23`
246 return bits.RotateLeft32(n, 9)
249 func RotateLeft16(n uint16, s int) uint16 {
250 // amd64:"ROLW" 386:"ROLW"
251 // arm64:"RORW",-"CSEL"
252 return bits.RotateLeft16(n, s)
255 func RotateLeft8(n uint8, s int) uint8 {
256 // amd64:"ROLB" 386:"ROLB"
257 // arm64:"LSL","LSR",-"CSEL"
258 return bits.RotateLeft8(n, s)
261 func RotateLeftVariable(n uint, m int) uint {
267 return bits.RotateLeft(n, m)
270 func RotateLeftVariable64(n uint64, m int) uint64 {
276 return bits.RotateLeft64(n, m)
279 func RotateLeftVariable32(n uint32, m int) uint32 {
280 // arm:`MOVW\tR[0-9]+@>R[0-9]+`
286 return bits.RotateLeft32(n, m)
289 // ------------------------ //
290 // bits.TrailingZeros //
291 // ------------------------ //
293 func TrailingZeros(n uint) int {
294 // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ"
298 // arm64:"RBIT","CLZ"
300 // ppc64x/power8:"ANDN","POPCNTD"
301 // ppc64x/power9: "CNTTZD"
303 return bits.TrailingZeros(n)
306 func TrailingZeros64(n uint64) int {
307 // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ"
310 // arm64:"RBIT","CLZ"
312 // ppc64x/power8:"ANDN","POPCNTD"
313 // ppc64x/power9: "CNTTZD"
315 return bits.TrailingZeros64(n)
318 func TrailingZeros64Subtract(n uint64) int {
319 // ppc64x/power8:"NEG","SUBC","ANDN","POPCNTD"
320 // ppc64x/power9:"SUBC","CNTTZD"
321 return bits.TrailingZeros64(1 - n)
324 func TrailingZeros32(n uint32) int {
325 // amd64/v1,amd64/v2:"BTSQ\\t\\$32","BSFQ"
329 // arm64:"RBITW","CLZW"
330 // s390x:"FLOGR","MOVWZ"
331 // ppc64x/power8:"ANDN","POPCNTW"
332 // ppc64x/power9: "CNTTZW"
334 return bits.TrailingZeros32(n)
337 func TrailingZeros16(n uint16) int {
338 // amd64:"BSFL","BTSL\\t\\$16"
340 // arm:"ORR\t\\$65536","CLZ",-"MOVHU\tR"
341 // arm64:"ORR\t\\$65536","RBITW","CLZW",-"MOVHU\tR",-"RBIT\t",-"CLZ\t"
342 // s390x:"FLOGR","OR\t\\$65536"
343 // ppc64x/power8:"POPCNTD","OR\\t\\$65536"
344 // ppc64x/power9:"CNTTZD","OR\\t\\$65536"
346 return bits.TrailingZeros16(n)
349 func TrailingZeros8(n uint8) int {
350 // amd64:"BSFL","BTSL\\t\\$8"
352 // arm:"ORR\t\\$256","CLZ",-"MOVBU\tR"
353 // arm64:"ORR\t\\$256","RBITW","CLZW",-"MOVBU\tR",-"RBIT\t",-"CLZ\t"
354 // s390x:"FLOGR","OR\t\\$256"
356 return bits.TrailingZeros8(n)
359 // IterateBitsNN checks special handling of TrailingZerosNN when the input is known to be non-zero.
361 func IterateBits(n uint) int {
364 // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ"
366 i += bits.TrailingZeros(n)
372 func IterateBits64(n uint64) int {
375 // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ"
377 i += bits.TrailingZeros64(n)
383 func IterateBits32(n uint32) int {
386 // amd64/v1,amd64/v2:"BSFL",-"BTSQ"
388 i += bits.TrailingZeros32(n)
394 func IterateBits16(n uint16) int {
397 // amd64/v1,amd64/v2:"BSFL",-"BTSL"
399 // arm64:"RBITW","CLZW",-"ORR"
400 i += bits.TrailingZeros16(n)
406 func IterateBits8(n uint8) int {
409 // amd64/v1,amd64/v2:"BSFL",-"BTSL"
411 // arm64:"RBITW","CLZW",-"ORR"
412 i += bits.TrailingZeros8(n)
418 // --------------- //
420 // --------------- //
422 func Add(x, y, ci uint) (r, co uint) {
423 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
424 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
425 // ppc64x: "ADDC", "ADDE", "ADDZE"
426 // s390x:"ADDE","ADDC\t[$]-1,"
427 // riscv64: "ADD","SLTU"
428 return bits.Add(x, y, ci)
431 func AddC(x, ci uint) (r, co uint) {
432 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
433 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
434 // loong64: "ADDV", "SGTU"
435 // ppc64x: "ADDC", "ADDE", "ADDZE"
436 // s390x:"ADDE","ADDC\t[$]-1,"
437 // mips64:"ADDV","SGTU"
438 // riscv64: "ADD","SLTU"
439 return bits.Add(x, 7, ci)
442 func AddZ(x, y uint) (r, co uint) {
443 // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
444 // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
445 // loong64: "ADDV", "SGTU"
446 // ppc64x: "ADDC", -"ADDE", "ADDZE"
447 // s390x:"ADDC",-"ADDC\t[$]-1,"
448 // mips64:"ADDV","SGTU"
449 // riscv64: "ADD","SLTU"
450 return bits.Add(x, y, 0)
453 func AddR(x, y, ci uint) uint {
454 // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
455 // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
456 // loong64: "ADDV", -"SGTU"
457 // ppc64x: "ADDC", "ADDE", -"ADDZE"
458 // s390x:"ADDE","ADDC\t[$]-1,"
459 // mips64:"ADDV",-"SGTU"
460 // riscv64: "ADD",-"SLTU"
461 r, _ := bits.Add(x, y, ci)
465 func AddM(p, q, r *[3]uint) {
467 r[0], c = bits.Add(p[0], q[0], c)
468 // arm64:"ADCS",-"ADD\t",-"CMP"
469 // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
470 // s390x:"ADDE",-"ADDC\t[$]-1,"
471 r[1], c = bits.Add(p[1], q[1], c)
472 r[2], c = bits.Add(p[2], q[2], c)
475 func Add64(x, y, ci uint64) (r, co uint64) {
476 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
477 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
478 // loong64: "ADDV", "SGTU"
479 // ppc64x: "ADDC", "ADDE", "ADDZE"
480 // s390x:"ADDE","ADDC\t[$]-1,"
481 // mips64:"ADDV","SGTU"
482 // riscv64: "ADD","SLTU"
483 return bits.Add64(x, y, ci)
486 func Add64C(x, ci uint64) (r, co uint64) {
487 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
488 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
489 // loong64: "ADDV", "SGTU"
490 // ppc64x: "ADDC", "ADDE", "ADDZE"
491 // s390x:"ADDE","ADDC\t[$]-1,"
492 // mips64:"ADDV","SGTU"
493 // riscv64: "ADD","SLTU"
494 return bits.Add64(x, 7, ci)
497 func Add64Z(x, y uint64) (r, co uint64) {
498 // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
499 // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
500 // loong64: "ADDV", "SGTU"
501 // ppc64x: "ADDC", -"ADDE", "ADDZE"
502 // s390x:"ADDC",-"ADDC\t[$]-1,"
503 // mips64:"ADDV","SGTU"
504 // riscv64: "ADD","SLTU"
505 return bits.Add64(x, y, 0)
508 func Add64R(x, y, ci uint64) uint64 {
509 // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
510 // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
511 // loong64: "ADDV", -"SGTU"
512 // ppc64x: "ADDC", "ADDE", -"ADDZE"
513 // s390x:"ADDE","ADDC\t[$]-1,"
514 // mips64:"ADDV",-"SGTU"
515 // riscv64: "ADD",-"SLTU"
516 r, _ := bits.Add64(x, y, ci)
519 func Add64M(p, q, r *[3]uint64) {
521 r[0], c = bits.Add64(p[0], q[0], c)
522 // arm64:"ADCS",-"ADD\t",-"CMP"
523 // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
524 // ppc64x: -"ADDC", "ADDE", -"ADDZE"
525 // s390x:"ADDE",-"ADDC\t[$]-1,"
526 r[1], c = bits.Add64(p[1], q[1], c)
527 r[2], c = bits.Add64(p[2], q[2], c)
530 func Add64MSaveC(p, q, r, c *[2]uint64) {
531 // ppc64x: "ADDC\tR", "ADDZE"
532 r[0], c[0] = bits.Add64(p[0], q[0], 0)
533 // ppc64x: "ADDC\t[$]-1", "ADDE", "ADDZE"
534 r[1], c[1] = bits.Add64(p[1], q[1], c[0])
537 func Add64PanicOnOverflowEQ(a, b uint64) uint64 {
538 r, c := bits.Add64(a, b, 0)
539 // s390x:"BRC\t[$]3,",-"ADDE"
546 func Add64PanicOnOverflowNE(a, b uint64) uint64 {
547 r, c := bits.Add64(a, b, 0)
548 // s390x:"BRC\t[$]3,",-"ADDE"
555 func Add64PanicOnOverflowGT(a, b uint64) uint64 {
556 r, c := bits.Add64(a, b, 0)
557 // s390x:"BRC\t[$]3,",-"ADDE"
564 func Add64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
567 r[0], c = bits.Add64(a[0], b[0], c)
568 r[1], c = bits.Add64(a[1], b[1], c)
569 // s390x:"BRC\t[$]3,"
576 func Add64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
579 r[0], c = bits.Add64(a[0], b[0], c)
580 r[1], c = bits.Add64(a[1], b[1], c)
581 // s390x:"BRC\t[$]3,"
588 func Add64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
591 r[0], c = bits.Add64(a[0], b[0], c)
592 r[1], c = bits.Add64(a[1], b[1], c)
593 // s390x:"BRC\t[$]3,"
600 // Verify independent carry chain operations are scheduled efficiently
601 // and do not cause unnecessary save/restore of the CA bit.
603 // This is an example of why CarryChainTail priority must be lower
604 // (earlier in the block) than Memory. f[0]=f1 could be scheduled
605 // after the first two lower 64 bit limb adds, but before either
606 // high 64 bit limbs are added.
608 // This is what happened on PPC64 when compiling
609 // crypto/internal/edwards25519/field.feMulGeneric.
610 func Add64MultipleChains(a, b, c, d [2]uint64) {
611 var cx, d1, d2 uint64
616 // ppc64x: "ADDC\tR\\d+,", -"ADDE", -"MOVD\tXER"
617 d1, cx = bits.Add64(a1, b1, 0)
618 // ppc64x: "ADDE", -"ADDC", -"MOVD\t.*, XER"
619 d2, _ = bits.Add64(a2, b2, cx)
621 // ppc64x: "ADDC\tR\\d+,", -"ADDE", -"MOVD\tXER"
622 d1, cx = bits.Add64(c1, d1, 0)
623 // ppc64x: "ADDE", -"ADDC", -"MOVD\t.*, XER"
624 d2, _ = bits.Add64(c2, d2, cx)
629 // --------------- //
631 // --------------- //
633 func Sub(x, y, ci uint) (r, co uint) {
634 // amd64:"NEGL","SBBQ","NEGQ"
635 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
636 // loong64:"SUBV","SGTU"
637 // ppc64x:"SUBC", "SUBE", "SUBZE", "NEG"
639 // riscv64: "SUB","SLTU"
640 return bits.Sub(x, y, ci)
643 func SubC(x, ci uint) (r, co uint) {
644 // amd64:"NEGL","SBBQ","NEGQ"
645 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
646 // loong64:"SUBV","SGTU"
647 // ppc64x:"SUBC", "SUBE", "SUBZE", "NEG"
649 // riscv64: "SUB","SLTU"
650 return bits.Sub(x, 7, ci)
653 func SubZ(x, y uint) (r, co uint) {
654 // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
655 // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
656 // loong64:"SUBV","SGTU"
657 // ppc64x:"SUBC", -"SUBE", "SUBZE", "NEG"
659 // riscv64: "SUB","SLTU"
660 return bits.Sub(x, y, 0)
663 func SubR(x, y, ci uint) uint {
664 // amd64:"NEGL","SBBQ",-"NEGQ"
665 // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
666 // loong64:"SUBV",-"SGTU"
667 // ppc64x:"SUBC", "SUBE", -"SUBZE", -"NEG"
669 // riscv64: "SUB",-"SLTU"
670 r, _ := bits.Sub(x, y, ci)
673 func SubM(p, q, r *[3]uint) {
675 r[0], c = bits.Sub(p[0], q[0], c)
676 // amd64:"SBBQ",-"NEGL",-"NEGQ"
677 // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
678 // ppc64x:-"SUBC", "SUBE", -"SUBZE", -"NEG"
680 r[1], c = bits.Sub(p[1], q[1], c)
681 r[2], c = bits.Sub(p[2], q[2], c)
684 func Sub64(x, y, ci uint64) (r, co uint64) {
685 // amd64:"NEGL","SBBQ","NEGQ"
686 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
687 // loong64:"SUBV","SGTU"
688 // ppc64x:"SUBC", "SUBE", "SUBZE", "NEG"
690 // riscv64: "SUB","SLTU"
691 return bits.Sub64(x, y, ci)
694 func Sub64C(x, ci uint64) (r, co uint64) {
695 // amd64:"NEGL","SBBQ","NEGQ"
696 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
697 // loong64:"SUBV","SGTU"
698 // ppc64x:"SUBC", "SUBE", "SUBZE", "NEG"
700 // riscv64: "SUB","SLTU"
701 return bits.Sub64(x, 7, ci)
704 func Sub64Z(x, y uint64) (r, co uint64) {
705 // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
706 // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
707 // loong64:"SUBV","SGTU"
708 // ppc64x:"SUBC", -"SUBE", "SUBZE", "NEG"
710 // riscv64: "SUB","SLTU"
711 return bits.Sub64(x, y, 0)
714 func Sub64R(x, y, ci uint64) uint64 {
715 // amd64:"NEGL","SBBQ",-"NEGQ"
716 // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
717 // loong64:"SUBV",-"SGTU"
718 // ppc64x:"SUBC", "SUBE", -"SUBZE", -"NEG"
720 // riscv64: "SUB",-"SLTU"
721 r, _ := bits.Sub64(x, y, ci)
724 func Sub64M(p, q, r *[3]uint64) {
726 r[0], c = bits.Sub64(p[0], q[0], c)
727 // amd64:"SBBQ",-"NEGL",-"NEGQ"
728 // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
730 r[1], c = bits.Sub64(p[1], q[1], c)
731 r[2], c = bits.Sub64(p[2], q[2], c)
734 func Sub64MSaveC(p, q, r, c *[2]uint64) {
735 // ppc64x:"SUBC\tR\\d+, R\\d+,", "SUBZE", "NEG"
736 r[0], c[0] = bits.Sub64(p[0], q[0], 0)
737 // ppc64x:"SUBC\tR\\d+, [$]0,", "SUBE", "SUBZE", "NEG"
738 r[1], c[1] = bits.Sub64(p[1], q[1], c[0])
741 func Sub64PanicOnOverflowEQ(a, b uint64) uint64 {
742 r, b := bits.Sub64(a, b, 0)
743 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
750 func Sub64PanicOnOverflowNE(a, b uint64) uint64 {
751 r, b := bits.Sub64(a, b, 0)
752 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
759 func Sub64PanicOnOverflowGT(a, b uint64) uint64 {
760 r, b := bits.Sub64(a, b, 0)
761 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
768 func Sub64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
771 r[0], c = bits.Sub64(a[0], b[0], c)
772 r[1], c = bits.Sub64(a[1], b[1], c)
773 // s390x:"BRC\t[$]12,"
780 func Sub64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
783 r[0], c = bits.Sub64(a[0], b[0], c)
784 r[1], c = bits.Sub64(a[1], b[1], c)
785 // s390x:"BRC\t[$]12,"
792 func Sub64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
795 r[0], c = bits.Sub64(a[0], b[0], c)
796 r[1], c = bits.Sub64(a[1], b[1], c)
797 // s390x:"BRC\t[$]12,"
804 // --------------- //
806 // --------------- //
808 func Mul(x, y uint) (hi, lo uint) {
810 // arm64:"UMULH","MUL"
811 // ppc64x:"MULHDU","MULLD"
814 return bits.Mul(x, y)
817 func Mul64(x, y uint64) (hi, lo uint64) {
819 // arm64:"UMULH","MUL"
820 // ppc64x:"MULHDU","MULLD"
823 // riscv64:"MULHU","MUL"
824 return bits.Mul64(x, y)
827 func Mul64HiOnly(x, y uint64) uint64 {
828 // arm64:"UMULH",-"MUL"
829 // riscv64:"MULHU",-"MUL\t"
830 hi, _ := bits.Mul64(x, y)
834 func Mul64LoOnly(x, y uint64) uint64 {
835 // arm64:"MUL",-"UMULH"
836 // riscv64:"MUL\t",-"MULHU"
837 _, lo := bits.Mul64(x, y)
841 // --------------- //
843 // --------------- //
845 func Div(hi, lo, x uint) (q, r uint) {
847 return bits.Div(hi, lo, x)
850 func Div32(hi, lo, x uint32) (q, r uint32) {
851 // arm64:"ORR","UDIV","MSUB",-"UREM"
852 return bits.Div32(hi, lo, x)
855 func Div64(hi, lo, x uint64) (q, r uint64) {
857 return bits.Div64(hi, lo, x)
860 func Div64degenerate(x uint64) (q, r uint64) {
862 return bits.Div64(0, x, 5)