]> Cypherpunks.ru repositories - gostls13.git/blob - test/codegen/mathbits.go
[dev.boringcrypto] all: merge commit 9d0819b27c (CL 314609) into dev.boringcrypto
[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:"BSFQ","MOVL\t\\$64","CMOVQEQ"
276         // arm:"CLZ"
277         // arm64:"RBIT","CLZ"
278         // s390x:"FLOGR"
279         // ppc64/power8:"ANDN","POPCNTD"
280         // ppc64le/power8:"ANDN","POPCNTD"
281         // ppc64/power9: "CNTTZD"
282         // ppc64le/power9: "CNTTZD"
283         // wasm:"I64Ctz"
284         return bits.TrailingZeros(n)
285 }
286
287 func TrailingZeros64(n uint64) int {
288         // amd64:"BSFQ","MOVL\t\\$64","CMOVQEQ"
289         // arm64:"RBIT","CLZ"
290         // s390x:"FLOGR"
291         // ppc64/power8:"ANDN","POPCNTD"
292         // ppc64le/power8:"ANDN","POPCNTD"
293         // ppc64/power9: "CNTTZD"
294         // ppc64le/power9: "CNTTZD"
295         // wasm:"I64Ctz"
296         return bits.TrailingZeros64(n)
297 }
298
299 func TrailingZeros64Subtract(n uint64) int {
300         // ppc64le/power8:"NEG","SUBC","ANDN","POPCNTD"
301         // ppc64le/power9:"SUBC","CNTTZD"
302         return bits.TrailingZeros64(1 - n)
303 }
304
305 func TrailingZeros32(n uint32) int {
306         // amd64:"BTSQ\\t\\$32","BSFQ"
307         // arm:"CLZ"
308         // arm64:"RBITW","CLZW"
309         // s390x:"FLOGR","MOVWZ"
310         // ppc64/power8:"ANDN","POPCNTW"
311         // ppc64le/power8:"ANDN","POPCNTW"
312         // ppc64/power9: "CNTTZW"
313         // ppc64le/power9: "CNTTZW"
314         // wasm:"I64Ctz"
315         return bits.TrailingZeros32(n)
316 }
317
318 func TrailingZeros16(n uint16) int {
319         // amd64:"BSFL","BTSL\\t\\$16"
320         // 386:"BSFL\t"
321         // arm:"ORR\t\\$65536","CLZ",-"MOVHU\tR"
322         // arm64:"ORR\t\\$65536","RBITW","CLZW",-"MOVHU\tR",-"RBIT\t",-"CLZ\t"
323         // s390x:"FLOGR","OR\t\\$65536"
324         // ppc64/power8:"POPCNTD","OR\\t\\$65536"
325         // ppc64le/power8:"POPCNTD","OR\\t\\$65536"
326         // ppc64/power9:"CNTTZD","OR\\t\\$65536"
327         // ppc64le/power9:"CNTTZD","OR\\t\\$65536"
328         // wasm:"I64Ctz"
329         return bits.TrailingZeros16(n)
330 }
331
332 func TrailingZeros8(n uint8) int {
333         // amd64:"BSFL","BTSL\\t\\$8"
334         // arm:"ORR\t\\$256","CLZ",-"MOVBU\tR"
335         // arm64:"ORR\t\\$256","RBITW","CLZW",-"MOVBU\tR",-"RBIT\t",-"CLZ\t"
336         // s390x:"FLOGR","OR\t\\$256"
337         // wasm:"I64Ctz"
338         return bits.TrailingZeros8(n)
339 }
340
341 // IterateBitsNN checks special handling of TrailingZerosNN when the input is known to be non-zero.
342
343 func IterateBits(n uint) int {
344         i := 0
345         for n != 0 {
346                 // amd64:"BSFQ",-"CMOVEQ"
347                 i += bits.TrailingZeros(n)
348                 n &= n - 1
349         }
350         return i
351 }
352
353 func IterateBits64(n uint64) int {
354         i := 0
355         for n != 0 {
356                 // amd64:"BSFQ",-"CMOVEQ"
357                 i += bits.TrailingZeros64(n)
358                 n &= n - 1
359         }
360         return i
361 }
362
363 func IterateBits32(n uint32) int {
364         i := 0
365         for n != 0 {
366                 // amd64:"BSFL",-"BTSQ"
367                 i += bits.TrailingZeros32(n)
368                 n &= n - 1
369         }
370         return i
371 }
372
373 func IterateBits16(n uint16) int {
374         i := 0
375         for n != 0 {
376                 // amd64:"BSFL",-"BTSL"
377                 // arm64:"RBITW","CLZW",-"ORR"
378                 i += bits.TrailingZeros16(n)
379                 n &= n - 1
380         }
381         return i
382 }
383
384 func IterateBits8(n uint8) int {
385         i := 0
386         for n != 0 {
387                 // amd64:"BSFL",-"BTSL"
388                 // arm64:"RBITW","CLZW",-"ORR"
389                 i += bits.TrailingZeros8(n)
390                 n &= n - 1
391         }
392         return i
393 }
394
395 // --------------- //
396 //    bits.Add*    //
397 // --------------- //
398
399 func Add(x, y, ci uint) (r, co uint) {
400         // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
401         // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
402         // s390x:"ADDE","ADDC\t[$]-1,"
403         return bits.Add(x, y, ci)
404 }
405
406 func AddC(x, ci uint) (r, co uint) {
407         // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
408         // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
409         // s390x:"ADDE","ADDC\t[$]-1,"
410         return bits.Add(x, 7, ci)
411 }
412
413 func AddZ(x, y uint) (r, co uint) {
414         // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
415         // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
416         // s390x:"ADDC",-"ADDC\t[$]-1,"
417         return bits.Add(x, y, 0)
418 }
419
420 func AddR(x, y, ci uint) uint {
421         // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
422         // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
423         // s390x:"ADDE","ADDC\t[$]-1,"
424         r, _ := bits.Add(x, y, ci)
425         return r
426 }
427
428 func AddM(p, q, r *[3]uint) {
429         var c uint
430         r[0], c = bits.Add(p[0], q[0], c)
431         // arm64:"ADCS",-"ADD\t",-"CMP"
432         // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
433         // s390x:"ADDE",-"ADDC\t[$]-1,"
434         r[1], c = bits.Add(p[1], q[1], c)
435         r[2], c = bits.Add(p[2], q[2], c)
436 }
437
438 func Add64(x, y, ci uint64) (r, co uint64) {
439         // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
440         // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
441         // ppc64: "ADDC", "ADDE", "ADDZE"
442         // ppc64le: "ADDC", "ADDE", "ADDZE"
443         // s390x:"ADDE","ADDC\t[$]-1,"
444         return bits.Add64(x, y, ci)
445 }
446
447 func Add64C(x, ci uint64) (r, co uint64) {
448         // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
449         // amd64:"NEGL","ADCQ","SBBQ","NEGQ"
450         // ppc64: "ADDC", "ADDE", "ADDZE"
451         // ppc64le: "ADDC", "ADDE", "ADDZE"
452         // s390x:"ADDE","ADDC\t[$]-1,"
453         return bits.Add64(x, 7, ci)
454 }
455
456 func Add64Z(x, y uint64) (r, co uint64) {
457         // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
458         // amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
459         // ppc64: "ADDC", "ADDE", "ADDZE"
460         // ppc64le: "ADDC", "ADDE", "ADDZE"
461         // s390x:"ADDC",-"ADDC\t[$]-1,"
462         return bits.Add64(x, y, 0)
463 }
464
465 func Add64R(x, y, ci uint64) uint64 {
466         // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
467         // amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
468         // ppc64: "ADDC", "ADDE", "ADDZE"
469         // ppc64le: "ADDC", "ADDE", "ADDZE"
470         // s390x:"ADDE","ADDC\t[$]-1,"
471         r, _ := bits.Add64(x, y, ci)
472         return r
473 }
474 func Add64M(p, q, r *[3]uint64) {
475         var c uint64
476         r[0], c = bits.Add64(p[0], q[0], c)
477         // arm64:"ADCS",-"ADD\t",-"CMP"
478         // amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
479         // ppc64: "ADDC", "ADDE", "ADDZE"
480         // ppc64le: "ADDC", "ADDE", "ADDZE"
481         // s390x:"ADDE",-"ADDC\t[$]-1,"
482         r[1], c = bits.Add64(p[1], q[1], c)
483         r[2], c = bits.Add64(p[2], q[2], c)
484 }
485
486 func Add64PanicOnOverflowEQ(a, b uint64) uint64 {
487         r, c := bits.Add64(a, b, 0)
488         // s390x:"BRC\t[$]3,",-"ADDE"
489         if c == 1 {
490                 panic("overflow")
491         }
492         return r
493 }
494
495 func Add64PanicOnOverflowNE(a, b uint64) uint64 {
496         r, c := bits.Add64(a, b, 0)
497         // s390x:"BRC\t[$]3,",-"ADDE"
498         if c != 0 {
499                 panic("overflow")
500         }
501         return r
502 }
503
504 func Add64PanicOnOverflowGT(a, b uint64) uint64 {
505         r, c := bits.Add64(a, b, 0)
506         // s390x:"BRC\t[$]3,",-"ADDE"
507         if c > 0 {
508                 panic("overflow")
509         }
510         return r
511 }
512
513 func Add64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
514         var r [2]uint64
515         var c uint64
516         r[0], c = bits.Add64(a[0], b[0], c)
517         r[1], c = bits.Add64(a[1], b[1], c)
518         // s390x:"BRC\t[$]3,"
519         if c == 1 {
520                 panic("overflow")
521         }
522         return r
523 }
524
525 func Add64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
526         var r [2]uint64
527         var c 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,"
531         if c != 0 {
532                 panic("overflow")
533         }
534         return r
535 }
536
537 func Add64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
538         var r [2]uint64
539         var c 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,"
543         if c > 0 {
544                 panic("overflow")
545         }
546         return r
547 }
548
549 // --------------- //
550 //    bits.Sub*    //
551 // --------------- //
552
553 func Sub(x, y, ci uint) (r, co uint) {
554         // amd64:"NEGL","SBBQ","NEGQ"
555         // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
556         // s390x:"SUBE"
557         return bits.Sub(x, y, ci)
558 }
559
560 func SubC(x, ci uint) (r, co uint) {
561         // amd64:"NEGL","SBBQ","NEGQ"
562         // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
563         // s390x:"SUBE"
564         return bits.Sub(x, 7, ci)
565 }
566
567 func SubZ(x, y uint) (r, co uint) {
568         // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
569         // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
570         // s390x:"SUBC"
571         return bits.Sub(x, y, 0)
572 }
573
574 func SubR(x, y, ci uint) uint {
575         // amd64:"NEGL","SBBQ",-"NEGQ"
576         // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
577         // s390x:"SUBE"
578         r, _ := bits.Sub(x, y, ci)
579         return r
580 }
581 func SubM(p, q, r *[3]uint) {
582         var c uint
583         r[0], c = bits.Sub(p[0], q[0], c)
584         // amd64:"SBBQ",-"NEGL",-"NEGQ"
585         // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
586         // s390x:"SUBE"
587         r[1], c = bits.Sub(p[1], q[1], c)
588         r[2], c = bits.Sub(p[2], q[2], c)
589 }
590
591 func Sub64(x, y, ci uint64) (r, co uint64) {
592         // amd64:"NEGL","SBBQ","NEGQ"
593         // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
594         // s390x:"SUBE"
595         return bits.Sub64(x, y, ci)
596 }
597
598 func Sub64C(x, ci uint64) (r, co uint64) {
599         // amd64:"NEGL","SBBQ","NEGQ"
600         // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
601         // s390x:"SUBE"
602         return bits.Sub64(x, 7, ci)
603 }
604
605 func Sub64Z(x, y uint64) (r, co uint64) {
606         // amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
607         // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
608         // s390x:"SUBC"
609         return bits.Sub64(x, y, 0)
610 }
611
612 func Sub64R(x, y, ci uint64) uint64 {
613         // amd64:"NEGL","SBBQ",-"NEGQ"
614         // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
615         // s390x:"SUBE"
616         r, _ := bits.Sub64(x, y, ci)
617         return r
618 }
619 func Sub64M(p, q, r *[3]uint64) {
620         var c uint64
621         r[0], c = bits.Sub64(p[0], q[0], c)
622         // amd64:"SBBQ",-"NEGL",-"NEGQ"
623         // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
624         // s390x:"SUBE"
625         r[1], c = bits.Sub64(p[1], q[1], c)
626         r[2], c = bits.Sub64(p[2], q[2], c)
627 }
628
629 func Sub64PanicOnOverflowEQ(a, b uint64) uint64 {
630         r, b := bits.Sub64(a, b, 0)
631         // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
632         if b == 1 {
633                 panic("overflow")
634         }
635         return r
636 }
637
638 func Sub64PanicOnOverflowNE(a, b uint64) uint64 {
639         r, b := bits.Sub64(a, b, 0)
640         // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
641         if b != 0 {
642                 panic("overflow")
643         }
644         return r
645 }
646
647 func Sub64PanicOnOverflowGT(a, b uint64) uint64 {
648         r, b := bits.Sub64(a, b, 0)
649         // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
650         if b > 0 {
651                 panic("overflow")
652         }
653         return r
654 }
655
656 func Sub64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
657         var r [2]uint64
658         var c uint64
659         r[0], c = bits.Sub64(a[0], b[0], c)
660         r[1], c = bits.Sub64(a[1], b[1], c)
661         // s390x:"BRC\t[$]12,"
662         if c == 1 {
663                 panic("overflow")
664         }
665         return r
666 }
667
668 func Sub64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
669         var r [2]uint64
670         var c 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,"
674         if c != 0 {
675                 panic("overflow")
676         }
677         return r
678 }
679
680 func Sub64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
681         var r [2]uint64
682         var c 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,"
686         if c > 0 {
687                 panic("overflow")
688         }
689         return r
690 }
691
692 // --------------- //
693 //    bits.Mul*    //
694 // --------------- //
695
696 func Mul(x, y uint) (hi, lo uint) {
697         // amd64:"MULQ"
698         // arm64:"UMULH","MUL"
699         // ppc64:"MULHDU","MULLD"
700         // ppc64le:"MULHDU","MULLD"
701         // s390x:"MLGR"
702         // mips64: "MULVU"
703         return bits.Mul(x, y)
704 }
705
706 func Mul64(x, y uint64) (hi, lo uint64) {
707         // amd64:"MULQ"
708         // arm64:"UMULH","MUL"
709         // ppc64:"MULHDU","MULLD"
710         // ppc64le:"MULHDU","MULLD"
711         // s390x:"MLGR"
712         // mips64: "MULVU"
713         return bits.Mul64(x, y)
714 }
715
716 // --------------- //
717 //    bits.Div*    //
718 // --------------- //
719
720 func Div(hi, lo, x uint) (q, r uint) {
721         // amd64:"DIVQ"
722         return bits.Div(hi, lo, x)
723 }
724
725 func Div32(hi, lo, x uint32) (q, r uint32) {
726         // arm64:"ORR","UDIV","MSUB",-"UREM"
727         return bits.Div32(hi, lo, x)
728 }
729
730 func Div64(hi, lo, x uint64) (q, r uint64) {
731         // amd64:"DIVQ"
732         return bits.Div64(hi, lo, x)
733 }
734
735 func Div64degenerate(x uint64) (q, r uint64) {
736         // amd64:-"DIVQ"
737         return bits.Div64(0, x, 5)
738 }