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
11var sval64 [8]int64
12var sval32 [8]int32
13var sval16 [8]int16
14var sval8 [8]int8
15var val64 [8]uint64
16var val32 [8]uint32
17var val16 [8]uint16
18var val8 [8]uint8
19
20// Avoid zero/sign extensions following a load
21// which has extended the value correctly.
22// Note: No tests are done for int8 since
23// an extra extension is usually needed due to
24// no signed byte load.
25
26func set16(x8 int8, u8 *uint8, y8 int8, z8 uint8) {
27	// Truncate not needed, load does sign/zero extend
28
29	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
30	val16[0] = uint16(*u8)
31
32	// AND not needed due to size
33	// ppc64x:-"ANDCC"
34	sval16[1] = 255 & int16(x8+y8)
35
36	// ppc64x:-"ANDCC"
37	val16[1] = 255 & uint16(*u8+z8)
38
39}
40func shiftidx(u8 *uint8, x16 *int16, u16 *uint16) {
41
42	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
43	val16[0] = uint16(sval16[*u8>>2])
44
45	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
46	sval16[1] = int16(val16[*x16>>1])
47
48	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
49	val16[1] = uint16(sval16[*u16>>2])
50
51}
52
53func setnox(x8 int8, u8 *uint8, y8 *int8, z8 *uint8, x16 *int16, u16 *uint16, x32 *int32, u32 *uint32) {
54
55	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
56	val16[0] = uint16(*u8)
57
58	// AND not needed due to size
59	// ppc64x:-"ANDCC"
60	sval16[1] = 255 & int16(x8+*y8)
61
62	// ppc64x:-"ANDCC"
63	val16[1] = 255 & uint16(*u8+*z8)
64
65	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
66	sval32[1] = int32(*x16)
67
68	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
69	val32[0] = uint32(*u8)
70
71	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
72	val32[1] = uint32(*u16)
73
74	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
75	sval64[1] = int64(*x16)
76
77	// ppc64x:-"MOVW\tR\\d+,\\sR\\d+"
78	sval64[2] = int64(*x32)
79
80	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
81	val64[0] = uint64(*u8)
82
83	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
84	val64[1] = uint64(*u16)
85
86	// ppc64x:-"MOVWZ\tR\\d+,\\sR\\d+"
87	val64[2] = uint64(*u32)
88}
89
90func cmp16(u8 *uint8, x32 *int32, u32 *uint32, x64 *int64, u64 *uint64) bool {
91
92	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
93	if uint16(*u8) == val16[0] {
94		return true
95	}
96
97	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
98	if uint16(*u32>>16) == val16[0] {
99		return true
100	}
101
102	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
103	if uint16(*u64>>48) == val16[0] {
104		return true
105	}
106
107	// Verify the truncates are using the correct sign.
108	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
109	if int16(*x32) == sval16[0] {
110		return true
111	}
112
113	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
114	if uint16(*u32) == val16[0] {
115		return true
116	}
117
118	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
119	if int16(*x64) == sval16[0] {
120		return true
121	}
122
123	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
124	if uint16(*u64) == val16[0] {
125		return true
126	}
127
128	return false
129}
130
131func cmp32(u8 *uint8, x16 *int16, u16 *uint16, x64 *int64, u64 *uint64) bool {
132
133	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
134	if uint32(*u8) == val32[0] {
135		return true
136	}
137
138	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
139	if int32(*x16) == sval32[0] {
140		return true
141	}
142
143	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
144	if uint32(*u16) == val32[0] {
145		return true
146	}
147
148	// Verify the truncates are using the correct sign.
149	// ppc64x:-"MOVWZ\tR\\d+,\\sR\\d+"
150	if int32(*x64) == sval32[0] {
151		return true
152	}
153
154	// ppc64x:-"MOVW\tR\\d+,\\sR\\d+"
155	if uint32(*u64) == val32[0] {
156		return true
157	}
158
159	return false
160}
161
162func cmp64(u8 *uint8, x16 *int16, u16 *uint16, x32 *int32, u32 *uint32) bool {
163
164	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
165	if uint64(*u8) == val64[0] {
166		return true
167	}
168
169	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
170	if int64(*x16) == sval64[0] {
171		return true
172	}
173
174	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
175	if uint64(*u16) == val64[0] {
176		return true
177	}
178
179	// ppc64x:-"MOVW\tR\\d+,\\sR\\d+"
180	if int64(*x32) == sval64[0] {
181		return true
182	}
183
184	// ppc64x:-"MOVWZ\tR\\d+,\\sR\\d+"
185	if uint64(*u32) == val64[0] {
186		return true
187	}
188	return false
189}
190
191// no unsign extension following 32 bits ops
192
193func noUnsignEXT(t1, t2, t3, t4 uint32, k int64) uint64 {
194	var ret uint64
195
196	// arm64:"RORW",-"MOVWU"
197	ret += uint64(bits.RotateLeft32(t1, 7))
198
199	// arm64:"MULW",-"MOVWU"
200	ret *= uint64(t1 * t2)
201
202	// arm64:"MNEGW",-"MOVWU"
203	ret += uint64(-t1 * t3)
204
205	// arm64:"UDIVW",-"MOVWU"
206	ret += uint64(t1 / t4)
207
208	// arm64:-"MOVWU"
209	ret += uint64(t2 % t3)
210
211	// arm64:"MSUBW",-"MOVWU"
212	ret += uint64(t1 - t2*t3)
213
214	// arm64:"MADDW",-"MOVWU"
215	ret += uint64(t3*t4 + t2)
216
217	// arm64:"REVW",-"MOVWU"
218	ret += uint64(bits.ReverseBytes32(t1))
219
220	// arm64:"RBITW",-"MOVWU"
221	ret += uint64(bits.Reverse32(t1))
222
223	// arm64:"CLZW",-"MOVWU"
224	ret += uint64(bits.LeadingZeros32(t1))
225
226	// arm64:"REV16W",-"MOVWU"
227	ret += uint64(((t1 & 0xff00ff00) >> 8) | ((t1 & 0x00ff00ff) << 8))
228
229	// arm64:"EXTRW",-"MOVWU"
230	ret += uint64((t1 << 25) | (t2 >> 7))
231
232	return ret
233}
234
235// no sign extension when the upper bits of the result are zero
236
237func noSignEXT(x int) int64 {
238	t1 := int32(x)
239
240	var ret int64
241
242	// arm64:-"MOVW"
243	ret += int64(t1 & 1)
244
245	// arm64:-"MOVW"
246	ret += int64(int32(x & 0x7fffffff))
247
248	// arm64:-"MOVH"
249	ret += int64(int16(x & 0x7fff))
250
251	// arm64:-"MOVB"
252	ret += int64(int8(x & 0x7f))
253
254	return ret
255}
256
257// corner cases that sign extension must not be omitted
258
259func shouldSignEXT(x int) int64 {
260	t1 := int32(x)
261
262	var ret int64
263
264	// arm64:"MOVW"
265	ret += int64(t1 & (-1))
266
267	// arm64:"MOVW"
268	ret += int64(int32(x & 0x80000000))
269
270	// arm64:"MOVW"
271	ret += int64(int32(x & 0x1100000011111111))
272
273	// arm64:"MOVH"
274	ret += int64(int16(x & 0x1100000000001111))
275
276	// arm64:"MOVB"
277	ret += int64(int8(x & 0x1100000000000011))
278
279	return ret
280}
281
282func noIntermediateExtension(a, b, c uint32) uint32 {
283	// arm64:-"MOVWU"
284	return a*b*9 + c
285}
286