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 {
18 // arm:"CLZ" arm64:"CLZ"
21 return bits.LeadingZeros(n)
24 func LeadingZeros64(n uint64) int {
27 // arm:"CLZ" arm64:"CLZ"
30 return bits.LeadingZeros64(n)
33 func LeadingZeros32(n uint32) int {
34 // amd64:"BSRQ","LEAQ",-"CMOVQEQ"
36 // arm:"CLZ" arm64:"CLZW"
39 return bits.LeadingZeros32(n)
42 func LeadingZeros16(n uint16) int {
43 // amd64:"BSRL","LEAL",-"CMOVQEQ"
45 // arm:"CLZ" arm64:"CLZ"
48 return bits.LeadingZeros16(n)
51 func LeadingZeros8(n uint8) int {
52 // amd64:"BSRL","LEAL",-"CMOVQEQ"
54 // arm:"CLZ" arm64:"CLZ"
57 return bits.LeadingZeros8(n)
64 func Len(n uint) int {
67 // arm:"CLZ" arm64:"CLZ"
73 func Len64(n uint64) int {
76 // arm:"CLZ" arm64:"CLZ"
79 // ppc64le:"SUBC","CNTLZD"
80 // ppc64:"SUBC","CNTLZD"
84 func SubFromLen64(n uint64) int {
85 // ppc64le:"CNTLZD",-"SUBC"
86 // ppc64:"CNTLZD",-"SUBC"
87 return 64 - bits.Len64(n)
90 func Len32(n uint32) int {
91 // amd64:"BSRQ","LEAQ",-"CMOVQEQ"
93 // arm:"CLZ" arm64:"CLZ"
99 func Len16(n uint16) int {
100 // amd64:"BSRL","LEAL",-"CMOVQEQ"
102 // arm:"CLZ" arm64:"CLZ"
108 func Len8(n uint8) int {
109 // amd64:"BSRL","LEAL",-"CMOVQEQ"
111 // arm:"CLZ" arm64:"CLZ"
117 // -------------------- //
119 // -------------------- //
121 // TODO(register args) Restore a m d 6 4 / v 1 :.*x86HasPOPCNT when only one ABI is tested.
122 func OnesCount(n uint) int {
123 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
125 // arm64:"VCNT","VUADDLV"
130 return bits.OnesCount(n)
133 func OnesCount64(n uint64) int {
134 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
136 // arm64:"VCNT","VUADDLV"
141 return bits.OnesCount64(n)
144 func OnesCount32(n uint32) int {
145 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
147 // arm64:"VCNT","VUADDLV"
152 return bits.OnesCount32(n)
155 func OnesCount16(n uint16) int {
156 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
158 // arm64:"VCNT","VUADDLV"
163 return bits.OnesCount16(n)
166 func OnesCount8(n uint8) int {
171 return bits.OnesCount8(n)
174 // ----------------------- //
175 // bits.ReverseBytes //
176 // ----------------------- //
178 func ReverseBytes(n uint) uint {
182 return bits.ReverseBytes(n)
185 func ReverseBytes64(n uint64) uint64 {
189 return bits.ReverseBytes64(n)
192 func ReverseBytes32(n uint32) uint32 {
196 return bits.ReverseBytes32(n)
199 func ReverseBytes16(n uint16) uint16 {
201 // arm64:"REV16W",-"UBFX",-"ORR"
202 // arm/5:"SLL","SRL","ORR"
205 return bits.ReverseBytes16(n)
208 // --------------------- //
209 // bits.RotateLeft //
210 // --------------------- //
212 func RotateLeft64(n uint64) uint64 {
217 // s390x:"RISBGZ\t[$]0, [$]63, [$]37, "
219 return bits.RotateLeft64(n, 37)
222 func RotateLeft32(n uint32) uint32 {
223 // amd64:"ROLL" 386:"ROLL"
224 // arm:`MOVW\tR[0-9]+@>23`
230 return bits.RotateLeft32(n, 9)
233 func RotateLeft16(n uint16) uint16 {
234 // amd64:"ROLW" 386:"ROLW"
235 return bits.RotateLeft16(n, 5)
238 func RotateLeft8(n uint8) uint8 {
239 // amd64:"ROLB" 386:"ROLB"
240 return bits.RotateLeft8(n, 5)
243 func RotateLeftVariable(n uint, m int) uint {
250 return bits.RotateLeft(n, m)
253 func RotateLeftVariable64(n uint64, m int) uint64 {
260 return bits.RotateLeft64(n, m)
263 func RotateLeftVariable32(n uint32, m int) uint32 {
264 // arm:`MOVW\tR[0-9]+@>R[0-9]+`
271 return bits.RotateLeft32(n, m)
274 // ------------------------ //
275 // bits.TrailingZeros //
276 // ------------------------ //
278 func TrailingZeros(n uint) int {
279 // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ"
282 // arm64:"RBIT","CLZ"
284 // ppc64/power8:"ANDN","POPCNTD"
285 // ppc64le/power8:"ANDN","POPCNTD"
286 // ppc64/power9: "CNTTZD"
287 // ppc64le/power9: "CNTTZD"
289 return bits.TrailingZeros(n)
292 func TrailingZeros64(n uint64) int {
293 // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ"
295 // arm64:"RBIT","CLZ"
297 // ppc64/power8:"ANDN","POPCNTD"
298 // ppc64le/power8:"ANDN","POPCNTD"
299 // ppc64/power9: "CNTTZD"
300 // ppc64le/power9: "CNTTZD"
302 return bits.TrailingZeros64(n)
305 func TrailingZeros64Subtract(n uint64) int {
306 // ppc64le/power8:"NEG","SUBC","ANDN","POPCNTD"
307 // ppc64le/power9:"SUBC","CNTTZD"
308 return bits.TrailingZeros64(1 - n)
311 func TrailingZeros32(n uint32) int {
312 // amd64/v1,amd64/v2:"BTSQ\\t\\$32","BSFQ"
315 // arm64:"RBITW","CLZW"
316 // s390x:"FLOGR","MOVWZ"
317 // ppc64/power8:"ANDN","POPCNTW"
318 // ppc64le/power8:"ANDN","POPCNTW"
319 // ppc64/power9: "CNTTZW"
320 // ppc64le/power9: "CNTTZW"
322 return bits.TrailingZeros32(n)
325 func TrailingZeros16(n uint16) int {
326 // amd64:"BSFL","BTSL\\t\\$16"
328 // arm:"ORR\t\\$65536","CLZ",-"MOVHU\tR"
329 // arm64:"ORR\t\\$65536","RBITW","CLZW",-"MOVHU\tR",-"RBIT\t",-"CLZ\t"
330 // s390x:"FLOGR","OR\t\\$65536"
331 // ppc64/power8:"POPCNTD","OR\\t\\$65536"
332 // ppc64le/power8:"POPCNTD","OR\\t\\$65536"
333 // ppc64/power9:"CNTTZD","OR\\t\\$65536"
334 // ppc64le/power9:"CNTTZD","OR\\t\\$65536"
336 return bits.TrailingZeros16(n)
339 func TrailingZeros8(n uint8) int {
340 // amd64:"BSFL","BTSL\\t\\$8"
341 // arm:"ORR\t\\$256","CLZ",-"MOVBU\tR"
342 // arm64:"ORR\t\\$256","RBITW","CLZW",-"MOVBU\tR",-"RBIT\t",-"CLZ\t"
343 // s390x:"FLOGR","OR\t\\$256"
345 return bits.TrailingZeros8(n)
348 // IterateBitsNN checks special handling of TrailingZerosNN when the input is known to be non-zero.
350 func IterateBits(n uint) int {
353 // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ"
355 i += bits.TrailingZeros(n)
361 func IterateBits64(n uint64) int {
364 // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ"
366 i += bits.TrailingZeros64(n)
372 func IterateBits32(n uint32) int {
375 // amd64/v1,amd64/v2:"BSFL",-"BTSQ"
377 i += bits.TrailingZeros32(n)
383 func IterateBits16(n uint16) int {
386 // amd64/v1,amd64/v2:"BSFL",-"BTSL"
388 // arm64:"RBITW","CLZW",-"ORR"
389 i += bits.TrailingZeros16(n)
395 func IterateBits8(n uint8) int {
398 // amd64/v1,amd64/v2:"BSFL",-"BTSL"
400 // arm64:"RBITW","CLZW",-"ORR"
401 i += bits.TrailingZeros8(n)
407 // --------------- //
409 // --------------- //
411 func Add(x, y, ci uint) (r, co uint) {
412 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
413 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
414 // s390x:"ADDE","ADDC\t[$]-1,"
415 return bits.Add(x, y, ci)
418 func AddC(x, ci uint) (r, co uint) {
419 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
420 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
421 // s390x:"ADDE","ADDC\t[$]-1,"
422 return bits.Add(x, 7, ci)
425 func AddZ(x, y uint) (r, co uint) {
426 // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
427 // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
428 // s390x:"ADDC",-"ADDC\t[$]-1,"
429 return bits.Add(x, y, 0)
432 func AddR(x, y, ci uint) uint {
433 // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
434 // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
435 // s390x:"ADDE","ADDC\t[$]-1,"
436 r, _ := bits.Add(x, y, ci)
440 func AddM(p, q, r *[3]uint) {
442 r[0], c = bits.Add(p[0], q[0], c)
443 // arm64:"ADCS",-"ADD\t",-"CMP"
444 // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
445 // s390x:"ADDE",-"ADDC\t[$]-1,"
446 r[1], c = bits.Add(p[1], q[1], c)
447 r[2], c = bits.Add(p[2], q[2], c)
450 func Add64(x, y, ci uint64) (r, co uint64) {
451 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
452 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
453 // ppc64: "ADDC", "ADDE", "ADDZE"
454 // ppc64le: "ADDC", "ADDE", "ADDZE"
455 // s390x:"ADDE","ADDC\t[$]-1,"
456 return bits.Add64(x, y, ci)
459 func Add64C(x, ci uint64) (r, co uint64) {
460 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
461 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
462 // ppc64: "ADDC", "ADDE", "ADDZE"
463 // ppc64le: "ADDC", "ADDE", "ADDZE"
464 // s390x:"ADDE","ADDC\t[$]-1,"
465 return bits.Add64(x, 7, ci)
468 func Add64Z(x, y uint64) (r, co uint64) {
469 // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
470 // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
471 // ppc64: "ADDC", "ADDE", "ADDZE"
472 // ppc64le: "ADDC", "ADDE", "ADDZE"
473 // s390x:"ADDC",-"ADDC\t[$]-1,"
474 return bits.Add64(x, y, 0)
477 func Add64R(x, y, ci uint64) uint64 {
478 // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
479 // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
480 // ppc64: "ADDC", "ADDE", "ADDZE"
481 // ppc64le: "ADDC", "ADDE", "ADDZE"
482 // s390x:"ADDE","ADDC\t[$]-1,"
483 r, _ := bits.Add64(x, y, ci)
486 func Add64M(p, q, r *[3]uint64) {
488 r[0], c = bits.Add64(p[0], q[0], c)
489 // arm64:"ADCS",-"ADD\t",-"CMP"
490 // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
491 // ppc64: "ADDC", "ADDE", "ADDZE"
492 // ppc64le: "ADDC", "ADDE", "ADDZE"
493 // s390x:"ADDE",-"ADDC\t[$]-1,"
494 r[1], c = bits.Add64(p[1], q[1], c)
495 r[2], c = bits.Add64(p[2], q[2], c)
498 func Add64PanicOnOverflowEQ(a, b uint64) uint64 {
499 r, c := bits.Add64(a, b, 0)
500 // s390x:"BRC\t[$]3,",-"ADDE"
507 func Add64PanicOnOverflowNE(a, b uint64) uint64 {
508 r, c := bits.Add64(a, b, 0)
509 // s390x:"BRC\t[$]3,",-"ADDE"
516 func Add64PanicOnOverflowGT(a, b uint64) uint64 {
517 r, c := bits.Add64(a, b, 0)
518 // s390x:"BRC\t[$]3,",-"ADDE"
525 func Add64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
528 r[0], c = bits.Add64(a[0], b[0], c)
529 r[1], c = bits.Add64(a[1], b[1], c)
530 // s390x:"BRC\t[$]3,"
537 func Add64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
540 r[0], c = bits.Add64(a[0], b[0], c)
541 r[1], c = bits.Add64(a[1], b[1], c)
542 // s390x:"BRC\t[$]3,"
549 func Add64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
552 r[0], c = bits.Add64(a[0], b[0], c)
553 r[1], c = bits.Add64(a[1], b[1], c)
554 // s390x:"BRC\t[$]3,"
561 // --------------- //
563 // --------------- //
565 func Sub(x, y, ci uint) (r, co uint) {
566 // amd64:"NEGL","SBBQ","NEGQ"
567 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
569 return bits.Sub(x, y, ci)
572 func SubC(x, ci uint) (r, co uint) {
573 // amd64:"NEGL","SBBQ","NEGQ"
574 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
576 return bits.Sub(x, 7, ci)
579 func SubZ(x, y uint) (r, co uint) {
580 // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
581 // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
583 return bits.Sub(x, y, 0)
586 func SubR(x, y, ci uint) uint {
587 // amd64:"NEGL","SBBQ",-"NEGQ"
588 // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
590 r, _ := bits.Sub(x, y, ci)
593 func SubM(p, q, r *[3]uint) {
595 r[0], c = bits.Sub(p[0], q[0], c)
596 // amd64:"SBBQ",-"NEGL",-"NEGQ"
597 // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
599 r[1], c = bits.Sub(p[1], q[1], c)
600 r[2], c = bits.Sub(p[2], q[2], c)
603 func Sub64(x, y, ci uint64) (r, co uint64) {
604 // amd64:"NEGL","SBBQ","NEGQ"
605 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
607 return bits.Sub64(x, y, ci)
610 func Sub64C(x, ci uint64) (r, co uint64) {
611 // amd64:"NEGL","SBBQ","NEGQ"
612 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
614 return bits.Sub64(x, 7, ci)
617 func Sub64Z(x, y uint64) (r, co uint64) {
618 // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
619 // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
621 return bits.Sub64(x, y, 0)
624 func Sub64R(x, y, ci uint64) uint64 {
625 // amd64:"NEGL","SBBQ",-"NEGQ"
626 // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
628 r, _ := bits.Sub64(x, y, ci)
631 func Sub64M(p, q, r *[3]uint64) {
633 r[0], c = bits.Sub64(p[0], q[0], c)
634 // amd64:"SBBQ",-"NEGL",-"NEGQ"
635 // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
637 r[1], c = bits.Sub64(p[1], q[1], c)
638 r[2], c = bits.Sub64(p[2], q[2], c)
641 func Sub64PanicOnOverflowEQ(a, b uint64) uint64 {
642 r, b := bits.Sub64(a, b, 0)
643 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
650 func Sub64PanicOnOverflowNE(a, b uint64) uint64 {
651 r, b := bits.Sub64(a, b, 0)
652 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
659 func Sub64PanicOnOverflowGT(a, b uint64) uint64 {
660 r, b := bits.Sub64(a, b, 0)
661 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
668 func Sub64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
671 r[0], c = bits.Sub64(a[0], b[0], c)
672 r[1], c = bits.Sub64(a[1], b[1], c)
673 // s390x:"BRC\t[$]12,"
680 func Sub64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
683 r[0], c = bits.Sub64(a[0], b[0], c)
684 r[1], c = bits.Sub64(a[1], b[1], c)
685 // s390x:"BRC\t[$]12,"
692 func Sub64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
695 r[0], c = bits.Sub64(a[0], b[0], c)
696 r[1], c = bits.Sub64(a[1], b[1], c)
697 // s390x:"BRC\t[$]12,"
704 // --------------- //
706 // --------------- //
708 func Mul(x, y uint) (hi, lo uint) {
710 // arm64:"UMULH","MUL"
711 // ppc64:"MULHDU","MULLD"
712 // ppc64le:"MULHDU","MULLD"
715 return bits.Mul(x, y)
718 func Mul64(x, y uint64) (hi, lo uint64) {
720 // arm64:"UMULH","MUL"
721 // ppc64:"MULHDU","MULLD"
722 // ppc64le:"MULHDU","MULLD"
725 // riscv64:"MULHU","MUL"
726 return bits.Mul64(x, y)
729 // --------------- //
731 // --------------- //
733 func Div(hi, lo, x uint) (q, r uint) {
735 return bits.Div(hi, lo, x)
738 func Div32(hi, lo, x uint32) (q, r uint32) {
739 // arm64:"ORR","UDIV","MSUB",-"UREM"
740 return bits.Div32(hi, lo, x)
743 func Div64(hi, lo, x uint64) (q, r uint64) {
745 return bits.Div64(hi, lo, x)
748 func Div64degenerate(x uint64) (q, r uint64) {
750 return bits.Div64(0, x, 5)