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"
101 func Len16(n uint16) int {
102 // amd64:"BSRL","LEAL",-"CMOVQEQ"
104 // arm:"CLZ" arm64:"CLZ"
110 func Len8(n uint8) int {
111 // amd64:"BSRL","LEAL",-"CMOVQEQ"
113 // arm:"CLZ" arm64:"CLZ"
119 // -------------------- //
121 // -------------------- //
123 // TODO(register args) Restore a m d 6 4 / v 1 :.*x86HasPOPCNT when only one ABI is tested.
124 func OnesCount(n uint) int {
125 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
127 // arm64:"VCNT","VUADDLV"
132 return bits.OnesCount(n)
135 func OnesCount64(n uint64) int {
136 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
138 // arm64:"VCNT","VUADDLV"
143 return bits.OnesCount64(n)
146 func OnesCount32(n uint32) int {
147 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
149 // arm64:"VCNT","VUADDLV"
154 return bits.OnesCount32(n)
157 func OnesCount16(n uint16) int {
158 // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT"
160 // arm64:"VCNT","VUADDLV"
165 return bits.OnesCount16(n)
168 func OnesCount8(n uint8) int {
173 return bits.OnesCount8(n)
176 // ----------------------- //
177 // bits.ReverseBytes //
178 // ----------------------- //
180 func ReverseBytes(n uint) uint {
184 return bits.ReverseBytes(n)
187 func ReverseBytes64(n uint64) uint64 {
191 return bits.ReverseBytes64(n)
194 func ReverseBytes32(n uint32) uint32 {
198 return bits.ReverseBytes32(n)
201 func ReverseBytes16(n uint16) uint16 {
203 // arm64:"REV16W",-"UBFX",-"ORR"
204 // arm/5:"SLL","SRL","ORR"
207 return bits.ReverseBytes16(n)
210 // --------------------- //
211 // bits.RotateLeft //
212 // --------------------- //
214 func RotateLeft64(n uint64) uint64 {
219 // s390x:"RISBGZ\t[$]0, [$]63, [$]37, "
221 return bits.RotateLeft64(n, 37)
224 func RotateLeft32(n uint32) uint32 {
225 // amd64:"ROLL" 386:"ROLL"
226 // arm:`MOVW\tR[0-9]+@>23`
232 return bits.RotateLeft32(n, 9)
235 func RotateLeft16(n uint16) uint16 {
236 // amd64:"ROLW" 386:"ROLW"
237 return bits.RotateLeft16(n, 5)
240 func RotateLeft8(n uint8) uint8 {
241 // amd64:"ROLB" 386:"ROLB"
242 return bits.RotateLeft8(n, 5)
245 func RotateLeftVariable(n uint, m int) uint {
252 return bits.RotateLeft(n, m)
255 func RotateLeftVariable64(n uint64, m int) uint64 {
262 return bits.RotateLeft64(n, m)
265 func RotateLeftVariable32(n uint32, m int) uint32 {
266 // arm:`MOVW\tR[0-9]+@>R[0-9]+`
273 return bits.RotateLeft32(n, m)
276 // ------------------------ //
277 // bits.TrailingZeros //
278 // ------------------------ //
280 func TrailingZeros(n uint) int {
281 // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ"
284 // arm64:"RBIT","CLZ"
286 // ppc64/power8:"ANDN","POPCNTD"
287 // ppc64le/power8:"ANDN","POPCNTD"
288 // ppc64/power9: "CNTTZD"
289 // ppc64le/power9: "CNTTZD"
291 return bits.TrailingZeros(n)
294 func TrailingZeros64(n uint64) int {
295 // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ"
297 // arm64:"RBIT","CLZ"
299 // ppc64/power8:"ANDN","POPCNTD"
300 // ppc64le/power8:"ANDN","POPCNTD"
301 // ppc64/power9: "CNTTZD"
302 // ppc64le/power9: "CNTTZD"
304 return bits.TrailingZeros64(n)
307 func TrailingZeros64Subtract(n uint64) int {
308 // ppc64le/power8:"NEG","SUBC","ANDN","POPCNTD"
309 // ppc64le/power9:"SUBC","CNTTZD"
310 return bits.TrailingZeros64(1 - n)
313 func TrailingZeros32(n uint32) int {
314 // amd64/v1,amd64/v2:"BTSQ\\t\\$32","BSFQ"
317 // arm64:"RBITW","CLZW"
318 // s390x:"FLOGR","MOVWZ"
319 // ppc64/power8:"ANDN","POPCNTW"
320 // ppc64le/power8:"ANDN","POPCNTW"
321 // ppc64/power9: "CNTTZW"
322 // ppc64le/power9: "CNTTZW"
324 return bits.TrailingZeros32(n)
327 func TrailingZeros16(n uint16) int {
328 // amd64:"BSFL","BTSL\\t\\$16"
330 // arm:"ORR\t\\$65536","CLZ",-"MOVHU\tR"
331 // arm64:"ORR\t\\$65536","RBITW","CLZW",-"MOVHU\tR",-"RBIT\t",-"CLZ\t"
332 // s390x:"FLOGR","OR\t\\$65536"
333 // ppc64/power8:"POPCNTD","OR\\t\\$65536"
334 // ppc64le/power8:"POPCNTD","OR\\t\\$65536"
335 // ppc64/power9:"CNTTZD","OR\\t\\$65536"
336 // ppc64le/power9:"CNTTZD","OR\\t\\$65536"
338 return bits.TrailingZeros16(n)
341 func TrailingZeros8(n uint8) int {
342 // amd64:"BSFL","BTSL\\t\\$8"
343 // arm:"ORR\t\\$256","CLZ",-"MOVBU\tR"
344 // arm64:"ORR\t\\$256","RBITW","CLZW",-"MOVBU\tR",-"RBIT\t",-"CLZ\t"
345 // s390x:"FLOGR","OR\t\\$256"
347 return bits.TrailingZeros8(n)
350 // IterateBitsNN checks special handling of TrailingZerosNN when the input is known to be non-zero.
352 func IterateBits(n uint) int {
355 // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ"
357 i += bits.TrailingZeros(n)
363 func IterateBits64(n uint64) int {
366 // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ"
368 i += bits.TrailingZeros64(n)
374 func IterateBits32(n uint32) int {
377 // amd64/v1,amd64/v2:"BSFL",-"BTSQ"
379 i += bits.TrailingZeros32(n)
385 func IterateBits16(n uint16) int {
388 // amd64/v1,amd64/v2:"BSFL",-"BTSL"
390 // arm64:"RBITW","CLZW",-"ORR"
391 i += bits.TrailingZeros16(n)
397 func IterateBits8(n uint8) int {
400 // amd64/v1,amd64/v2:"BSFL",-"BTSL"
402 // arm64:"RBITW","CLZW",-"ORR"
403 i += bits.TrailingZeros8(n)
409 // --------------- //
411 // --------------- //
413 func Add(x, y, ci uint) (r, co uint) {
414 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
415 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
416 // s390x:"ADDE","ADDC\t[$]-1,"
417 return bits.Add(x, y, ci)
420 func AddC(x, ci uint) (r, co uint) {
421 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
422 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
423 // s390x:"ADDE","ADDC\t[$]-1,"
424 return bits.Add(x, 7, ci)
427 func AddZ(x, y uint) (r, co uint) {
428 // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
429 // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
430 // s390x:"ADDC",-"ADDC\t[$]-1,"
431 return bits.Add(x, y, 0)
434 func AddR(x, y, ci uint) uint {
435 // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
436 // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
437 // s390x:"ADDE","ADDC\t[$]-1,"
438 r, _ := bits.Add(x, y, ci)
442 func AddM(p, q, r *[3]uint) {
444 r[0], c = bits.Add(p[0], q[0], c)
445 // arm64:"ADCS",-"ADD\t",-"CMP"
446 // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
447 // s390x:"ADDE",-"ADDC\t[$]-1,"
448 r[1], c = bits.Add(p[1], q[1], c)
449 r[2], c = bits.Add(p[2], q[2], c)
452 func Add64(x, y, ci uint64) (r, co uint64) {
453 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
454 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
455 // ppc64: "ADDC", "ADDE", "ADDZE"
456 // ppc64le: "ADDC", "ADDE", "ADDZE"
457 // s390x:"ADDE","ADDC\t[$]-1,"
458 return bits.Add64(x, y, ci)
461 func Add64C(x, ci uint64) (r, co uint64) {
462 // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
463 // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
464 // ppc64: "ADDC", "ADDE", "ADDZE"
465 // ppc64le: "ADDC", "ADDE", "ADDZE"
466 // s390x:"ADDE","ADDC\t[$]-1,"
467 return bits.Add64(x, 7, ci)
470 func Add64Z(x, y uint64) (r, co uint64) {
471 // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
472 // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
473 // ppc64: "ADDC", "ADDE", "ADDZE"
474 // ppc64le: "ADDC", "ADDE", "ADDZE"
475 // s390x:"ADDC",-"ADDC\t[$]-1,"
476 return bits.Add64(x, y, 0)
479 func Add64R(x, y, ci uint64) uint64 {
480 // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
481 // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
482 // ppc64: "ADDC", "ADDE", "ADDZE"
483 // ppc64le: "ADDC", "ADDE", "ADDZE"
484 // s390x:"ADDE","ADDC\t[$]-1,"
485 r, _ := bits.Add64(x, y, ci)
488 func Add64M(p, q, r *[3]uint64) {
490 r[0], c = bits.Add64(p[0], q[0], c)
491 // arm64:"ADCS",-"ADD\t",-"CMP"
492 // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
493 // ppc64: "ADDC", "ADDE", "ADDZE"
494 // ppc64le: "ADDC", "ADDE", "ADDZE"
495 // s390x:"ADDE",-"ADDC\t[$]-1,"
496 r[1], c = bits.Add64(p[1], q[1], c)
497 r[2], c = bits.Add64(p[2], q[2], c)
500 func Add64PanicOnOverflowEQ(a, b uint64) uint64 {
501 r, c := bits.Add64(a, b, 0)
502 // s390x:"BRC\t[$]3,",-"ADDE"
509 func Add64PanicOnOverflowNE(a, b uint64) uint64 {
510 r, c := bits.Add64(a, b, 0)
511 // s390x:"BRC\t[$]3,",-"ADDE"
518 func Add64PanicOnOverflowGT(a, b uint64) uint64 {
519 r, c := bits.Add64(a, b, 0)
520 // s390x:"BRC\t[$]3,",-"ADDE"
527 func Add64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
530 r[0], c = bits.Add64(a[0], b[0], c)
531 r[1], c = bits.Add64(a[1], b[1], c)
532 // s390x:"BRC\t[$]3,"
539 func Add64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
542 r[0], c = bits.Add64(a[0], b[0], c)
543 r[1], c = bits.Add64(a[1], b[1], c)
544 // s390x:"BRC\t[$]3,"
551 func Add64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
554 r[0], c = bits.Add64(a[0], b[0], c)
555 r[1], c = bits.Add64(a[1], b[1], c)
556 // s390x:"BRC\t[$]3,"
563 // --------------- //
565 // --------------- //
567 func Sub(x, y, ci uint) (r, co uint) {
568 // amd64:"NEGL","SBBQ","NEGQ"
569 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
571 return bits.Sub(x, y, ci)
574 func SubC(x, ci uint) (r, co uint) {
575 // amd64:"NEGL","SBBQ","NEGQ"
576 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
578 return bits.Sub(x, 7, ci)
581 func SubZ(x, y uint) (r, co uint) {
582 // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
583 // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
585 return bits.Sub(x, y, 0)
588 func SubR(x, y, ci uint) uint {
589 // amd64:"NEGL","SBBQ",-"NEGQ"
590 // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
592 r, _ := bits.Sub(x, y, ci)
595 func SubM(p, q, r *[3]uint) {
597 r[0], c = bits.Sub(p[0], q[0], c)
598 // amd64:"SBBQ",-"NEGL",-"NEGQ"
599 // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
601 r[1], c = bits.Sub(p[1], q[1], c)
602 r[2], c = bits.Sub(p[2], q[2], c)
605 func Sub64(x, y, ci uint64) (r, co uint64) {
606 // amd64:"NEGL","SBBQ","NEGQ"
607 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
609 return bits.Sub64(x, y, ci)
612 func Sub64C(x, ci uint64) (r, co uint64) {
613 // amd64:"NEGL","SBBQ","NEGQ"
614 // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
616 return bits.Sub64(x, 7, ci)
619 func Sub64Z(x, y uint64) (r, co uint64) {
620 // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
621 // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
623 return bits.Sub64(x, y, 0)
626 func Sub64R(x, y, ci uint64) uint64 {
627 // amd64:"NEGL","SBBQ",-"NEGQ"
628 // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
630 r, _ := bits.Sub64(x, y, ci)
633 func Sub64M(p, q, r *[3]uint64) {
635 r[0], c = bits.Sub64(p[0], q[0], c)
636 // amd64:"SBBQ",-"NEGL",-"NEGQ"
637 // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
639 r[1], c = bits.Sub64(p[1], q[1], c)
640 r[2], c = bits.Sub64(p[2], q[2], c)
643 func Sub64PanicOnOverflowEQ(a, b uint64) uint64 {
644 r, b := bits.Sub64(a, b, 0)
645 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
652 func Sub64PanicOnOverflowNE(a, b uint64) uint64 {
653 r, b := bits.Sub64(a, b, 0)
654 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
661 func Sub64PanicOnOverflowGT(a, b uint64) uint64 {
662 r, b := bits.Sub64(a, b, 0)
663 // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
670 func Sub64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
673 r[0], c = bits.Sub64(a[0], b[0], c)
674 r[1], c = bits.Sub64(a[1], b[1], c)
675 // s390x:"BRC\t[$]12,"
682 func Sub64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
685 r[0], c = bits.Sub64(a[0], b[0], c)
686 r[1], c = bits.Sub64(a[1], b[1], c)
687 // s390x:"BRC\t[$]12,"
694 func Sub64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
697 r[0], c = bits.Sub64(a[0], b[0], c)
698 r[1], c = bits.Sub64(a[1], b[1], c)
699 // s390x:"BRC\t[$]12,"
706 // --------------- //
708 // --------------- //
710 func Mul(x, y uint) (hi, lo uint) {
712 // arm64:"UMULH","MUL"
713 // ppc64:"MULHDU","MULLD"
714 // ppc64le:"MULHDU","MULLD"
717 return bits.Mul(x, y)
720 func Mul64(x, y uint64) (hi, lo uint64) {
722 // arm64:"UMULH","MUL"
723 // ppc64:"MULHDU","MULLD"
724 // ppc64le:"MULHDU","MULLD"
727 // riscv64:"MULHU","MUL"
728 return bits.Mul64(x, y)
731 // --------------- //
733 // --------------- //
735 func Div(hi, lo, x uint) (q, r uint) {
737 return bits.Div(hi, lo, x)
740 func Div32(hi, lo, x uint32) (q, r uint32) {
741 // arm64:"ORR","UDIV","MSUB",-"UREM"
742 return bits.Div32(hi, lo, x)
745 func Div64(hi, lo, x uint64) (q, r uint64) {
747 return bits.Div64(hi, lo, x)
750 func Div64degenerate(x uint64) (q, r uint64) {
752 return bits.Div64(0, x, 5)