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 * 64-bit instructions
13 ************************************/
14
15func bitcheck64_constleft(a uint64) (n int) {
16	// amd64:"BTQ\t[$]63"
17	if a&(1<<63) != 0 {
18		return 1
19	}
20	// amd64:"BTQ\t[$]60"
21	if a&(1<<60) != 0 {
22		return 1
23	}
24	// amd64:"BTL\t[$]0"
25	if a&(1<<0) != 0 {
26		return 1
27	}
28	return 0
29}
30
31func bitcheck64_constright(a [8]uint64) (n int) {
32	// amd64:"BTQ\t[$]63"
33	if (a[0]>>63)&1 != 0 {
34		return 1
35	}
36	// amd64:"BTQ\t[$]63"
37	if a[1]>>63 != 0 {
38		return 1
39	}
40	// amd64:"BTQ\t[$]63"
41	if a[2]>>63 == 0 {
42		return 1
43	}
44	// amd64:"BTQ\t[$]60"
45	if (a[3]>>60)&1 == 0 {
46		return 1
47	}
48	// amd64:"BTL\t[$]1"
49	if (a[4]>>1)&1 == 0 {
50		return 1
51	}
52	// amd64:"BTL\t[$]0"
53	if (a[5]>>0)&1 == 0 {
54		return 1
55	}
56	// amd64:"BTL\t[$]7"
57	if (a[6]>>5)&4 == 0 {
58		return 1
59	}
60	return 0
61}
62
63func bitcheck64_var(a, b uint64) (n int) {
64	// amd64:"BTQ"
65	if a&(1<<(b&63)) != 0 {
66		return 1
67	}
68	// amd64:"BTQ",-"BT.\t[$]0"
69	if (b>>(a&63))&1 != 0 {
70		return 1
71	}
72	return 0
73}
74
75func bitcheck64_mask(a uint64) (n int) {
76	// amd64:"BTQ\t[$]63"
77	if a&0x8000000000000000 != 0 {
78		return 1
79	}
80	// amd64:"BTQ\t[$]59"
81	if a&0x800000000000000 != 0 {
82		return 1
83	}
84	// amd64:"BTL\t[$]0"
85	if a&0x1 != 0 {
86		return 1
87	}
88	return 0
89}
90
91func biton64(a, b uint64) (n uint64) {
92	// amd64:"BTSQ"
93	n += b | (1 << (a & 63))
94
95	// amd64:"BTSQ\t[$]63"
96	n += a | (1 << 63)
97
98	// amd64:"BTSQ\t[$]60"
99	n += a | (1 << 60)
100
101	// amd64:"ORQ\t[$]1"
102	n += a | (1 << 0)
103
104	return n
105}
106
107func bitoff64(a, b uint64) (n uint64) {
108	// amd64:"BTRQ"
109	n += b &^ (1 << (a & 63))
110
111	// amd64:"BTRQ\t[$]63"
112	n += a &^ (1 << 63)
113
114	// amd64:"BTRQ\t[$]60"
115	n += a &^ (1 << 60)
116
117	// amd64:"ANDQ\t[$]-2"
118	n += a &^ (1 << 0)
119
120	return n
121}
122
123func bitcompl64(a, b uint64) (n uint64) {
124	// amd64:"BTCQ"
125	n += b ^ (1 << (a & 63))
126
127	// amd64:"BTCQ\t[$]63"
128	n += a ^ (1 << 63)
129
130	// amd64:"BTCQ\t[$]60"
131	n += a ^ (1 << 60)
132
133	// amd64:"XORQ\t[$]1"
134	n += a ^ (1 << 0)
135
136	return n
137}
138
139/************************************
140 * 32-bit instructions
141 ************************************/
142
143func bitcheck32_constleft(a uint32) (n int) {
144	// amd64:"BTL\t[$]31"
145	if a&(1<<31) != 0 {
146		return 1
147	}
148	// amd64:"BTL\t[$]28"
149	if a&(1<<28) != 0 {
150		return 1
151	}
152	// amd64:"BTL\t[$]0"
153	if a&(1<<0) != 0 {
154		return 1
155	}
156	return 0
157}
158
159func bitcheck32_constright(a [8]uint32) (n int) {
160	// amd64:"BTL\t[$]31"
161	if (a[0]>>31)&1 != 0 {
162		return 1
163	}
164	// amd64:"BTL\t[$]31"
165	if a[1]>>31 != 0 {
166		return 1
167	}
168	// amd64:"BTL\t[$]31"
169	if a[2]>>31 == 0 {
170		return 1
171	}
172	// amd64:"BTL\t[$]28"
173	if (a[3]>>28)&1 == 0 {
174		return 1
175	}
176	// amd64:"BTL\t[$]1"
177	if (a[4]>>1)&1 == 0 {
178		return 1
179	}
180	// amd64:"BTL\t[$]0"
181	if (a[5]>>0)&1 == 0 {
182		return 1
183	}
184	// amd64:"BTL\t[$]7"
185	if (a[6]>>5)&4 == 0 {
186		return 1
187	}
188	return 0
189}
190
191func bitcheck32_var(a, b uint32) (n int) {
192	// amd64:"BTL"
193	if a&(1<<(b&31)) != 0 {
194		return 1
195	}
196	// amd64:"BTL",-"BT.\t[$]0"
197	if (b>>(a&31))&1 != 0 {
198		return 1
199	}
200	return 0
201}
202
203func bitcheck32_mask(a uint32) (n int) {
204	// amd64:"BTL\t[$]31"
205	if a&0x80000000 != 0 {
206		return 1
207	}
208	// amd64:"BTL\t[$]27"
209	if a&0x8000000 != 0 {
210		return 1
211	}
212	// amd64:"BTL\t[$]0"
213	if a&0x1 != 0 {
214		return 1
215	}
216	return 0
217}
218
219func biton32(a, b uint32) (n uint32) {
220	// amd64:"BTSL"
221	n += b | (1 << (a & 31))
222
223	// amd64:"ORL\t[$]-2147483648"
224	n += a | (1 << 31)
225
226	// amd64:"ORL\t[$]268435456"
227	n += a | (1 << 28)
228
229	// amd64:"ORL\t[$]1"
230	n += a | (1 << 0)
231
232	return n
233}
234
235func bitoff32(a, b uint32) (n uint32) {
236	// amd64:"BTRL"
237	n += b &^ (1 << (a & 31))
238
239	// amd64:"ANDL\t[$]2147483647"
240	n += a &^ (1 << 31)
241
242	// amd64:"ANDL\t[$]-268435457"
243	n += a &^ (1 << 28)
244
245	// amd64:"ANDL\t[$]-2"
246	n += a &^ (1 << 0)
247
248	return n
249}
250
251func bitcompl32(a, b uint32) (n uint32) {
252	// amd64:"BTCL"
253	n += b ^ (1 << (a & 31))
254
255	// amd64:"XORL\t[$]-2147483648"
256	n += a ^ (1 << 31)
257
258	// amd64:"XORL\t[$]268435456"
259	n += a ^ (1 << 28)
260
261	// amd64:"XORL\t[$]1"
262	n += a ^ (1 << 0)
263
264	return n
265}
266
267// check direct operation on memory with constant and shifted constant sources
268func bitOpOnMem(a []uint32, b, c, d uint32) {
269	// amd64:`ANDL\s[$]200,\s\([A-Z][A-Z0-9]+\)`
270	a[0] &= 200
271	// amd64:`ORL\s[$]220,\s4\([A-Z][A-Z0-9]+\)`
272	a[1] |= 220
273	// amd64:`XORL\s[$]240,\s8\([A-Z][A-Z0-9]+\)`
274	a[2] ^= 240
275}
276
277func bitcheckMostNegative(b uint8) bool {
278	// amd64:"TESTB"
279	return b&0x80 == 0x80
280}
281
282// Check AND masking on arm64 (Issue #19857)
283
284func and_mask_1(a uint64) uint64 {
285	// arm64:`AND\t`
286	return a & ((1 << 63) - 1)
287}
288
289func and_mask_2(a uint64) uint64 {
290	// arm64:`AND\t`
291	return a & (1 << 63)
292}
293
294func and_mask_3(a, b uint32) (uint32, uint32) {
295	// arm/7:`BIC`,-`AND`
296	a &= 0xffffaaaa
297	// arm/7:`BFC`,-`AND`,-`BIC`
298	b &= 0xffc003ff
299	return a, b
300}
301
302// Check generation of arm64 BIC/EON/ORN instructions
303
304func op_bic(x, y uint32) uint32 {
305	// arm64:`BIC\t`,-`AND`
306	return x &^ y
307}
308
309func op_eon(x, y, z uint32, a []uint32, n, m uint64) uint64 {
310	// arm64:`EON\t`,-`EOR`,-`MVN`
311	a[0] = x ^ (y ^ 0xffffffff)
312
313	// arm64:`EON\t`,-`EOR`,-`MVN`
314	a[1] = ^(y ^ z)
315
316	// arm64:`EON\t`,-`XOR`
317	a[2] = x ^ ^z
318
319	// arm64:`EON\t`,-`EOR`,-`MVN`
320	return n ^ (m ^ 0xffffffffffffffff)
321}
322
323func op_orn(x, y uint32) uint32 {
324	// arm64:`ORN\t`,-`ORR`
325	return x | ^y
326}
327
328// check bitsets
329func bitSetPowerOf2Test(x int) bool {
330	// amd64:"BTL\t[$]3"
331	return x&8 == 8
332}
333
334func bitSetTest(x int) bool {
335	// amd64:"ANDL\t[$]9, AX"
336	// amd64:"CMPQ\tAX, [$]9"
337	return x&9 == 9
338}
339
340// mask contiguous one bits
341func cont1Mask64U(x uint64) uint64 {
342	// s390x:"RISBGZ\t[$]16, [$]47, [$]0,"
343	return x & 0x0000ffffffff0000
344}
345
346// mask contiguous zero bits
347func cont0Mask64U(x uint64) uint64 {
348	// s390x:"RISBGZ\t[$]48, [$]15, [$]0,"
349	return x & 0xffff00000000ffff
350}
351
352func issue44228a(a []int64, i int) bool {
353	// amd64: "BTQ", -"SHL"
354	return a[i>>6]&(1<<(i&63)) != 0
355}
356func issue44228b(a []int32, i int) bool {
357	// amd64: "BTL", -"SHL"
358	return a[i>>5]&(1<<(i&31)) != 0
359}
360
361func issue48467(x, y uint64) uint64 {
362	// arm64: -"NEG"
363	d, borrow := bits.Sub64(x, y, 0)
364	return x - d&(-borrow)
365}
366
367func foldConst(x, y uint64) uint64 {
368	// arm64: "ADDS\t[$]7",-"MOVD\t[$]7"
369	d, b := bits.Add64(x, 7, 0)
370	return b & d
371}
372
373func foldConstOutOfRange(a uint64) uint64 {
374	// arm64: "MOVD\t[$]19088744",-"ADD\t[$]19088744"
375	return a + 0x1234568
376}
377
378// Verify sign-extended values are not zero-extended under a bit mask (#61297)
379func signextendAndMask8to64(a int8) (s, z uint64) {
380	// ppc64x: "MOVB", "ANDCC\t[$]1015,"
381	s = uint64(a) & 0x3F7
382	// ppc64x: -"MOVB", "ANDCC\t[$]247,"
383	z = uint64(uint8(a)) & 0x3F7
384	return
385}
386
387// Verify zero-extended values are not sign-extended under a bit mask (#61297)
388func zeroextendAndMask8to64(a int8, b int16) (x, y uint64) {
389	// ppc64x: -"MOVB\t", -"ANDCC", "MOVBZ"
390	x = uint64(a) & 0xFF
391	// ppc64x: -"MOVH\t", -"ANDCC", "MOVHZ"
392	y = uint64(b) & 0xFFFF
393	return
394}
395
396// Verify rotate and mask instructions, and further simplified instructions for small types
397func bitRotateAndMask(io64 [8]uint64, io32 [4]uint32, io16 [4]uint16, io8 [4]uint8) {
398	// ppc64x: "RLDICR\t[$]0, R[0-9]*, [$]47, R"
399	io64[0] = io64[0] & 0xFFFFFFFFFFFF0000
400	// ppc64x: "RLDICL\t[$]0, R[0-9]*, [$]16, R"
401	io64[1] = io64[1] & 0x0000FFFFFFFFFFFF
402	// ppc64x: -"SRD", -"AND", "RLDICL\t[$]60, R[0-9]*, [$]16, R"
403	io64[2] = (io64[2] >> 4) & 0x0000FFFFFFFFFFFF
404	// ppc64x: -"SRD", -"AND", "RLDICL\t[$]36, R[0-9]*, [$]28, R"
405	io64[3] = (io64[3] >> 28) & 0x0000FFFFFFFFFFFF
406
407	// ppc64x: "MOVWZ", "RLWNM\t[$]1, R[0-9]*, [$]28, [$]3, R"
408	io64[4] = uint64(bits.RotateLeft32(io32[0], 1) & 0xF000000F)
409
410	// ppc64x: "RLWNM\t[$]0, R[0-9]*, [$]4, [$]19, R"
411	io32[0] = io32[0] & 0x0FFFF000
412	// ppc64x: "RLWNM\t[$]0, R[0-9]*, [$]20, [$]3, R"
413	io32[1] = io32[1] & 0xF0000FFF
414	// ppc64x: -"RLWNM", MOVD, AND
415	io32[2] = io32[2] & 0xFFFF0002
416
417	var bigc uint32 = 0x12345678
418	// ppc64x: "ANDCC\t[$]22136"
419	io16[0] = io16[0] & uint16(bigc)
420
421	// ppc64x: "ANDCC\t[$]120"
422	io8[0] = io8[0] & uint8(bigc)
423}
424