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