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