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