]> Cypherpunks.ru repositories - gostls13.git/blob - test/codegen/mathbits.go
cmd/compile: use TZCNT instruction for GOAMD64>=v3
[gostls13.git] / test / codegen / mathbits.go
1 // asmcheck
2
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.
6
7 package codegen
8
9 import "math/bits"
10
11 // ----------------------- //
12 //    bits.LeadingZeros    //
13 // ----------------------- //
14
15 func LeadingZeros(n uint) int {
16         // amd64:"BSRQ"
17         // s390x:"FLOGR"
18         // arm:"CLZ" arm64:"CLZ"
19         // mips:"CLZ"
20         // wasm:"I64Clz"
21         return bits.LeadingZeros(n)
22 }
23
24 func LeadingZeros64(n uint64) int {
25         // amd64:"BSRQ"
26         // s390x:"FLOGR"
27         // arm:"CLZ" arm64:"CLZ"
28         // mips:"CLZ"
29         // wasm:"I64Clz"
30         return bits.LeadingZeros64(n)
31 }
32
33 func LeadingZeros32(n uint32) int {
34         // amd64:"BSRQ","LEAQ",-"CMOVQEQ"
35         // s390x:"FLOGR"
36         // arm:"CLZ" arm64:"CLZW"
37         // mips:"CLZ"
38         // wasm:"I64Clz"
39         return bits.LeadingZeros32(n)
40 }
41
42 func LeadingZeros16(n uint16) int {
43         // amd64:"BSRL","LEAL",-"CMOVQEQ"
44         // s390x:"FLOGR"
45         // arm:"CLZ" arm64:"CLZ"
46         // mips:"CLZ"
47         // wasm:"I64Clz"
48         return bits.LeadingZeros16(n)
49 }
50
51 func LeadingZeros8(n uint8) int {
52         // amd64:"BSRL","LEAL",-"CMOVQEQ"
53         // s390x:"FLOGR"
54         // arm:"CLZ" arm64:"CLZ"
55         // mips:"CLZ"
56         // wasm:"I64Clz"
57         return bits.LeadingZeros8(n)
58 }
59
60 // --------------- //
61 //    bits.Len*    //
62 // --------------- //
63
64 func Len(n uint) int {
65         // amd64:"BSRQ"
66         // s390x:"FLOGR"
67         // arm:"CLZ" arm64:"CLZ"
68         // mips:"CLZ"
69         // wasm:"I64Clz"
70         return bits.Len(n)
71 }
72
73 func Len64(n uint64) int {
74         // amd64:"BSRQ"
75         // s390x:"FLOGR"
76         // arm:"CLZ" arm64:"CLZ"
77         // mips:"CLZ"
78         // wasm:"I64Clz"
79         // ppc64le:"SUBC","CNTLZD"
80         // ppc64:"SUBC","CNTLZD"
81         return bits.Len64(n)
82 }
83
84 func SubFromLen64(n uint64) int {
85         // ppc64le:"CNTLZD",-"SUBC"
86         // ppc64:"CNTLZD",-"SUBC"
87         return 64 - bits.Len64(n)
88 }
89
90 func Len32(n uint32) int {
91         // amd64:"BSRQ","LEAQ",-"CMOVQEQ"
92         // s390x:"FLOGR"
93         // arm:"CLZ" arm64:"CLZ"
94         // mips:"CLZ"
95         // wasm:"I64Clz"
96         return bits.Len32(n)
97 }
98
99 func Len16(n uint16) int {
100         // amd64:"BSRL","LEAL",-"CMOVQEQ"
101         // s390x:"FLOGR"
102         // arm:"CLZ" arm64:"CLZ"
103         // mips:"CLZ"
104         // wasm:"I64Clz"
105         return bits.Len16(n)
106 }
107
108 func Len8(n uint8) int {
109         // amd64:"BSRL","LEAL",-"CMOVQEQ"
110         // s390x:"FLOGR"
111         // arm:"CLZ" arm64:"CLZ"
112         // mips:"CLZ"
113         // wasm:"I64Clz"
114         return bits.Len8(n)
115 }
116
117 // -------------------- //
118 //    bits.OnesCount    //
119 // -------------------- //
120
121 // TODO(register args) Restore a m d 6 4 :.*x86HasPOPCNT when only one ABI is tested.
122 func OnesCount(n uint) int {
123         // amd64:"POPCNTQ"
124         // arm64:"VCNT","VUADDLV"
125         // s390x:"POPCNT"
126         // ppc64:"POPCNTD"
127         // ppc64le:"POPCNTD"
128         // wasm:"I64Popcnt"
129         return bits.OnesCount(n)
130 }
131
132 func OnesCount64(n uint64) int {
133         // amd64:"POPCNTQ"
134         // arm64:"VCNT","VUADDLV"
135         // s390x:"POPCNT"
136         // ppc64:"POPCNTD"
137         // ppc64le:"POPCNTD"
138         // wasm:"I64Popcnt"
139         return bits.OnesCount64(n)
140 }
141
142 func OnesCount32(n uint32) int {
143         // amd64:"POPCNTL"
144         // arm64:"VCNT","VUADDLV"
145         // s390x:"POPCNT"
146         // ppc64:"POPCNTW"
147         // ppc64le:"POPCNTW"
148         // wasm:"I64Popcnt"
149         return bits.OnesCount32(n)
150 }
151
152 func OnesCount16(n uint16) int {
153         // amd64:"POPCNTL"
154         // arm64:"VCNT","VUADDLV"
155         // s390x:"POPCNT"
156         // ppc64:"POPCNTW"
157         // ppc64le:"POPCNTW"
158         // wasm:"I64Popcnt"
159         return bits.OnesCount16(n)
160 }
161
162 func OnesCount8(n uint8) int {
163         // s390x:"POPCNT"
164         // ppc64:"POPCNTB"
165         // ppc64le:"POPCNTB"
166         // wasm:"I64Popcnt"
167         return bits.OnesCount8(n)
168 }
169
170 // ----------------------- //
171 //    bits.ReverseBytes    //
172 // ----------------------- //
173
174 func ReverseBytes(n uint) uint {
175         // amd64:"BSWAPQ"
176         // s390x:"MOVDBR"
177         // arm64:"REV"
178         return bits.ReverseBytes(n)
179 }
180
181 func ReverseBytes64(n uint64) uint64 {
182         // amd64:"BSWAPQ"
183         // s390x:"MOVDBR"
184         // arm64:"REV"
185         return bits.ReverseBytes64(n)
186 }
187
188 func ReverseBytes32(n uint32) uint32 {
189         // amd64:"BSWAPL"
190         // s390x:"MOVWBR"
191         // arm64:"REVW"
192         return bits.ReverseBytes32(n)
193 }
194
195 func ReverseBytes16(n uint16) uint16 {
196         // amd64:"ROLW"
197         // arm64:"REV16W",-"UBFX",-"ORR"
198         // arm/5:"SLL","SRL","ORR"
199         // arm/6:"REV16"
200         // arm/7:"REV16"
201         return bits.ReverseBytes16(n)
202 }
203
204 // --------------------- //
205 //    bits.RotateLeft    //
206 // --------------------- //
207
208 func RotateLeft64(n uint64) uint64 {
209         // amd64:"ROLQ"
210         // arm64:"ROR"
211         // ppc64:"ROTL"
212         // ppc64le:"ROTL"
213         // s390x:"RISBGZ\t[$]0, [$]63, [$]37, "
214         // wasm:"I64Rotl"
215         return bits.RotateLeft64(n, 37)
216 }
217
218 func RotateLeft32(n uint32) uint32 {
219         // amd64:"ROLL" 386:"ROLL"
220         // arm:`MOVW\tR[0-9]+@>23`
221         // arm64:"RORW"
222         // ppc64:"ROTLW"
223         // ppc64le:"ROTLW"
224         // s390x:"RLL"
225         // wasm:"I32Rotl"
226         return bits.RotateLeft32(n, 9)
227 }
228
229 func RotateLeft16(n uint16) uint16 {
230         // amd64:"ROLW" 386:"ROLW"
231         return bits.RotateLeft16(n, 5)
232 }
233
234 func RotateLeft8(n uint8) uint8 {
235         // amd64:"ROLB" 386:"ROLB"
236         return bits.RotateLeft8(n, 5)
237 }
238
239 func RotateLeftVariable(n uint, m int) uint {
240         // amd64:"ROLQ"
241         // arm64:"ROR"
242         // ppc64:"ROTL"
243         // ppc64le:"ROTL"
244         // s390x:"RLLG"
245         // wasm:"I64Rotl"
246         return bits.RotateLeft(n, m)
247 }
248
249 func RotateLeftVariable64(n uint64, m int) uint64 {
250         // amd64:"ROLQ"
251         // arm64:"ROR"
252         // ppc64:"ROTL"
253         // ppc64le:"ROTL"
254         // s390x:"RLLG"
255         // wasm:"I64Rotl"
256         return bits.RotateLeft64(n, m)
257 }
258
259 func RotateLeftVariable32(n uint32, m int) uint32 {
260         // arm:`MOVW\tR[0-9]+@>R[0-9]+`
261         // amd64:"ROLL"
262         // arm64:"RORW"
263         // ppc64:"ROTLW"
264         // ppc64le:"ROTLW"
265         // s390x:"RLL"
266         // wasm:"I32Rotl"
267         return bits.RotateLeft32(n, m)
268 }
269
270 // ------------------------ //
271 //    bits.TrailingZeros    //
272 // ------------------------ //
273
274 func TrailingZeros(n uint) int {
275         // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ"
276         // amd64/v3:"TZCNTQ"
277         // arm:"CLZ"
278         // arm64:"RBIT","CLZ"
279         // s390x:"FLOGR"
280         // ppc64/power8:"ANDN","POPCNTD"
281         // ppc64le/power8:"ANDN","POPCNTD"
282         // ppc64/power9: "CNTTZD"
283         // ppc64le/power9: "CNTTZD"
284         // wasm:"I64Ctz"
285         return bits.TrailingZeros(n)
286 }
287
288 func TrailingZeros64(n uint64) int {
289         // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ"
290         // amd64/v3:"TZCNTQ"
291         // arm64:"RBIT","CLZ"
292         // s390x:"FLOGR"
293         // ppc64/power8:"ANDN","POPCNTD"
294         // ppc64le/power8:"ANDN","POPCNTD"
295         // ppc64/power9: "CNTTZD"
296         // ppc64le/power9: "CNTTZD"
297         // wasm:"I64Ctz"
298         return bits.TrailingZeros64(n)
299 }
300
301 func TrailingZeros64Subtract(n uint64) int {
302         // ppc64le/power8:"NEG","SUBC","ANDN","POPCNTD"
303         // ppc64le/power9:"SUBC","CNTTZD"
304         return bits.TrailingZeros64(1 - n)
305 }
306
307 func TrailingZeros32(n uint32) int {
308         // amd64/v1,amd64/v2:"BTSQ\\t\\$32","BSFQ"
309         // amd64/v3:"TZCNTL"
310         // arm:"CLZ"
311         // arm64:"RBITW","CLZW"
312         // s390x:"FLOGR","MOVWZ"
313         // ppc64/power8:"ANDN","POPCNTW"
314         // ppc64le/power8:"ANDN","POPCNTW"
315         // ppc64/power9: "CNTTZW"
316         // ppc64le/power9: "CNTTZW"
317         // wasm:"I64Ctz"
318         return bits.TrailingZeros32(n)
319 }
320
321 func TrailingZeros16(n uint16) int {
322         // amd64:"BSFL","BTSL\\t\\$16"
323         // 386:"BSFL\t"
324         // arm:"ORR\t\\$65536","CLZ",-"MOVHU\tR"
325         // arm64:"ORR\t\\$65536","RBITW","CLZW",-"MOVHU\tR",-"RBIT\t",-"CLZ\t"
326         // s390x:"FLOGR","OR\t\\$65536"
327         // ppc64/power8:"POPCNTD","OR\\t\\$65536"
328         // ppc64le/power8:"POPCNTD","OR\\t\\$65536"
329         // ppc64/power9:"CNTTZD","OR\\t\\$65536"
330         // ppc64le/power9:"CNTTZD","OR\\t\\$65536"
331         // wasm:"I64Ctz"
332         return bits.TrailingZeros16(n)
333 }
334
335 func TrailingZeros8(n uint8) int {
336         // amd64:"BSFL","BTSL\\t\\$8"
337         // arm:"ORR\t\\$256","CLZ",-"MOVBU\tR"
338         // arm64:"ORR\t\\$256","RBITW","CLZW",-"MOVBU\tR",-"RBIT\t",-"CLZ\t"
339         // s390x:"FLOGR","OR\t\\$256"
340         // wasm:"I64Ctz"
341         return bits.TrailingZeros8(n)
342 }
343
344 // IterateBitsNN checks special handling of TrailingZerosNN when the input is known to be non-zero.
345
346 func IterateBits(n uint) int {
347         i := 0
348         for n != 0 {
349                 // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ"
350                 // amd64/v3:"TZCNTQ"
351                 i += bits.TrailingZeros(n)
352                 n &= n - 1
353         }
354         return i
355 }
356
357 func IterateBits64(n uint64) int {
358         i := 0
359         for n != 0 {
360                 // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ"
361                 // amd64/v3:"TZCNTQ"
362                 i += bits.TrailingZeros64(n)
363                 n &= n - 1
364         }
365         return i
366 }
367
368 func IterateBits32(n uint32) int {
369         i := 0
370         for n != 0 {
371                 // amd64/v1,amd64/v2:"BSFL",-"BTSQ"
372                 // amd64/v3:"TZCNTL"
373                 i += bits.TrailingZeros32(n)
374                 n &= n - 1
375         }
376         return i
377 }
378
379 func IterateBits16(n uint16) int {
380         i := 0
381         for n != 0 {
382                 // amd64/v1,amd64/v2:"BSFL",-"BTSL"
383                 // amd64/v3:"TZCNTL"
384                 // arm64:"RBITW","CLZW",-"ORR"
385                 i += bits.TrailingZeros16(n)
386                 n &= n - 1
387         }
388         return i
389 }
390
391 func IterateBits8(n uint8) int {
392         i := 0
393         for n != 0 {
394                 // amd64/v1,amd64/v2:"BSFL",-"BTSL"
395                 // amd64/v3:"TZCNTL"
396                 // arm64:"RBITW","CLZW",-"ORR"
397                 i += bits.TrailingZeros8(n)
398                 n &= n - 1
399         }
400         return i
401 }
402
403 // --------------- //
404 //    bits.Add*    //
405 // --------------- //
406
407 func Add(x, y, ci uint) (r, co uint) {
408         // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
409         // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
410         // s390x:"ADDE","ADDC\t[$]-1,"
411         return bits.Add(x, y, ci)
412 }
413
414 func AddC(x, ci uint) (r, co uint) {
415         // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
416         // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
417         // s390x:"ADDE","ADDC\t[$]-1,"
418         return bits.Add(x, 7, ci)
419 }
420
421 func AddZ(x, y uint) (r, co uint) {
422         // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
423         // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
424         // s390x:"ADDC",-"ADDC\t[$]-1,"
425         return bits.Add(x, y, 0)
426 }
427
428 func AddR(x, y, ci uint) uint {
429         // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
430         // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
431         // s390x:"ADDE","ADDC\t[$]-1,"
432         r, _ := bits.Add(x, y, ci)
433         return r
434 }
435
436 func AddM(p, q, r *[3]uint) {
437         var c uint
438         r[0], c = bits.Add(p[0], q[0], c)
439         // arm64:"ADCS",-"ADD\t",-"CMP"
440         // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
441         // s390x:"ADDE",-"ADDC\t[$]-1,"
442         r[1], c = bits.Add(p[1], q[1], c)
443         r[2], c = bits.Add(p[2], q[2], c)
444 }
445
446 func Add64(x, y, ci uint64) (r, co uint64) {
447         // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
448         // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
449         // ppc64: "ADDC", "ADDE", "ADDZE"
450         // ppc64le: "ADDC", "ADDE", "ADDZE"
451         // s390x:"ADDE","ADDC\t[$]-1,"
452         return bits.Add64(x, y, ci)
453 }
454
455 func Add64C(x, ci uint64) (r, co uint64) {
456         // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
457         // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
458         // ppc64: "ADDC", "ADDE", "ADDZE"
459         // ppc64le: "ADDC", "ADDE", "ADDZE"
460         // s390x:"ADDE","ADDC\t[$]-1,"
461         return bits.Add64(x, 7, ci)
462 }
463
464 func Add64Z(x, y uint64) (r, co uint64) {
465         // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
466         // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
467         // ppc64: "ADDC", "ADDE", "ADDZE"
468         // ppc64le: "ADDC", "ADDE", "ADDZE"
469         // s390x:"ADDC",-"ADDC\t[$]-1,"
470         return bits.Add64(x, y, 0)
471 }
472
473 func Add64R(x, y, ci uint64) uint64 {
474         // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
475         // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
476         // ppc64: "ADDC", "ADDE", "ADDZE"
477         // ppc64le: "ADDC", "ADDE", "ADDZE"
478         // s390x:"ADDE","ADDC\t[$]-1,"
479         r, _ := bits.Add64(x, y, ci)
480         return r
481 }
482 func Add64M(p, q, r *[3]uint64) {
483         var c uint64
484         r[0], c = bits.Add64(p[0], q[0], c)
485         // arm64:"ADCS",-"ADD\t",-"CMP"
486         // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
487         // ppc64: "ADDC", "ADDE", "ADDZE"
488         // ppc64le: "ADDC", "ADDE", "ADDZE"
489         // s390x:"ADDE",-"ADDC\t[$]-1,"
490         r[1], c = bits.Add64(p[1], q[1], c)
491         r[2], c = bits.Add64(p[2], q[2], c)
492 }
493
494 func Add64PanicOnOverflowEQ(a, b uint64) uint64 {
495         r, c := bits.Add64(a, b, 0)
496         // s390x:"BRC\t[$]3,",-"ADDE"
497         if c == 1 {
498                 panic("overflow")
499         }
500         return r
501 }
502
503 func Add64PanicOnOverflowNE(a, b uint64) uint64 {
504         r, c := bits.Add64(a, b, 0)
505         // s390x:"BRC\t[$]3,",-"ADDE"
506         if c != 0 {
507                 panic("overflow")
508         }
509         return r
510 }
511
512 func Add64PanicOnOverflowGT(a, b uint64) uint64 {
513         r, c := bits.Add64(a, b, 0)
514         // s390x:"BRC\t[$]3,",-"ADDE"
515         if c > 0 {
516                 panic("overflow")
517         }
518         return r
519 }
520
521 func Add64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
522         var r [2]uint64
523         var c uint64
524         r[0], c = bits.Add64(a[0], b[0], c)
525         r[1], c = bits.Add64(a[1], b[1], c)
526         // s390x:"BRC\t[$]3,"
527         if c == 1 {
528                 panic("overflow")
529         }
530         return r
531 }
532
533 func Add64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
534         var r [2]uint64
535         var c uint64
536         r[0], c = bits.Add64(a[0], b[0], c)
537         r[1], c = bits.Add64(a[1], b[1], c)
538         // s390x:"BRC\t[$]3,"
539         if c != 0 {
540                 panic("overflow")
541         }
542         return r
543 }
544
545 func Add64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
546         var r [2]uint64
547         var c uint64
548         r[0], c = bits.Add64(a[0], b[0], c)
549         r[1], c = bits.Add64(a[1], b[1], c)
550         // s390x:"BRC\t[$]3,"
551         if c > 0 {
552                 panic("overflow")
553         }
554         return r
555 }
556
557 // --------------- //
558 //    bits.Sub*    //
559 // --------------- //
560
561 func Sub(x, y, ci uint) (r, co uint) {
562         // amd64:"NEGL","SBBQ","NEGQ"
563         // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
564         // s390x:"SUBE"
565         return bits.Sub(x, y, ci)
566 }
567
568 func SubC(x, ci uint) (r, co uint) {
569         // amd64:"NEGL","SBBQ","NEGQ"
570         // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
571         // s390x:"SUBE"
572         return bits.Sub(x, 7, ci)
573 }
574
575 func SubZ(x, y uint) (r, co uint) {
576         // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
577         // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
578         // s390x:"SUBC"
579         return bits.Sub(x, y, 0)
580 }
581
582 func SubR(x, y, ci uint) uint {
583         // amd64:"NEGL","SBBQ",-"NEGQ"
584         // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
585         // s390x:"SUBE"
586         r, _ := bits.Sub(x, y, ci)
587         return r
588 }
589 func SubM(p, q, r *[3]uint) {
590         var c uint
591         r[0], c = bits.Sub(p[0], q[0], c)
592         // amd64:"SBBQ",-"NEGL",-"NEGQ"
593         // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
594         // s390x:"SUBE"
595         r[1], c = bits.Sub(p[1], q[1], c)
596         r[2], c = bits.Sub(p[2], q[2], c)
597 }
598
599 func Sub64(x, y, ci uint64) (r, co uint64) {
600         // amd64:"NEGL","SBBQ","NEGQ"
601         // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
602         // s390x:"SUBE"
603         return bits.Sub64(x, y, ci)
604 }
605
606 func Sub64C(x, ci uint64) (r, co uint64) {
607         // amd64:"NEGL","SBBQ","NEGQ"
608         // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
609         // s390x:"SUBE"
610         return bits.Sub64(x, 7, ci)
611 }
612
613 func Sub64Z(x, y uint64) (r, co uint64) {
614         // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
615         // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
616         // s390x:"SUBC"
617         return bits.Sub64(x, y, 0)
618 }
619
620 func Sub64R(x, y, ci uint64) uint64 {
621         // amd64:"NEGL","SBBQ",-"NEGQ"
622         // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
623         // s390x:"SUBE"
624         r, _ := bits.Sub64(x, y, ci)
625         return r
626 }
627 func Sub64M(p, q, r *[3]uint64) {
628         var c uint64
629         r[0], c = bits.Sub64(p[0], q[0], c)
630         // amd64:"SBBQ",-"NEGL",-"NEGQ"
631         // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
632         // s390x:"SUBE"
633         r[1], c = bits.Sub64(p[1], q[1], c)
634         r[2], c = bits.Sub64(p[2], q[2], c)
635 }
636
637 func Sub64PanicOnOverflowEQ(a, b uint64) uint64 {
638         r, b := bits.Sub64(a, b, 0)
639         // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
640         if b == 1 {
641                 panic("overflow")
642         }
643         return r
644 }
645
646 func Sub64PanicOnOverflowNE(a, b uint64) uint64 {
647         r, b := bits.Sub64(a, b, 0)
648         // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
649         if b != 0 {
650                 panic("overflow")
651         }
652         return r
653 }
654
655 func Sub64PanicOnOverflowGT(a, b uint64) uint64 {
656         r, b := bits.Sub64(a, b, 0)
657         // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
658         if b > 0 {
659                 panic("overflow")
660         }
661         return r
662 }
663
664 func Sub64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
665         var r [2]uint64
666         var c uint64
667         r[0], c = bits.Sub64(a[0], b[0], c)
668         r[1], c = bits.Sub64(a[1], b[1], c)
669         // s390x:"BRC\t[$]12,"
670         if c == 1 {
671                 panic("overflow")
672         }
673         return r
674 }
675
676 func Sub64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
677         var r [2]uint64
678         var c uint64
679         r[0], c = bits.Sub64(a[0], b[0], c)
680         r[1], c = bits.Sub64(a[1], b[1], c)
681         // s390x:"BRC\t[$]12,"
682         if c != 0 {
683                 panic("overflow")
684         }
685         return r
686 }
687
688 func Sub64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
689         var r [2]uint64
690         var c uint64
691         r[0], c = bits.Sub64(a[0], b[0], c)
692         r[1], c = bits.Sub64(a[1], b[1], c)
693         // s390x:"BRC\t[$]12,"
694         if c > 0 {
695                 panic("overflow")
696         }
697         return r
698 }
699
700 // --------------- //
701 //    bits.Mul*    //
702 // --------------- //
703
704 func Mul(x, y uint) (hi, lo uint) {
705         // amd64:"MULQ"
706         // arm64:"UMULH","MUL"
707         // ppc64:"MULHDU","MULLD"
708         // ppc64le:"MULHDU","MULLD"
709         // s390x:"MLGR"
710         // mips64: "MULVU"
711         return bits.Mul(x, y)
712 }
713
714 func Mul64(x, y uint64) (hi, lo uint64) {
715         // amd64:"MULQ"
716         // arm64:"UMULH","MUL"
717         // ppc64:"MULHDU","MULLD"
718         // ppc64le:"MULHDU","MULLD"
719         // s390x:"MLGR"
720         // mips64: "MULVU"
721         // riscv64:"MULHU","MUL"
722         return bits.Mul64(x, y)
723 }
724
725 // --------------- //
726 //    bits.Div*    //
727 // --------------- //
728
729 func Div(hi, lo, x uint) (q, r uint) {
730         // amd64:"DIVQ"
731         return bits.Div(hi, lo, x)
732 }
733
734 func Div32(hi, lo, x uint32) (q, r uint32) {
735         // arm64:"ORR","UDIV","MSUB",-"UREM"
736         return bits.Div32(hi, lo, x)
737 }
738
739 func Div64(hi, lo, x uint64) (q, r uint64) {
740         // amd64:"DIVQ"
741         return bits.Div64(hi, lo, x)
742 }
743
744 func Div64degenerate(x uint64) (q, r uint64) {
745         // amd64:-"DIVQ"
746         return bits.Div64(0, x, 5)
747 }