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//    const rotates    //
13// ------------------- //
14
15func rot64(x uint64) uint64 {
16	var a uint64
17
18	// amd64:"ROLQ\t[$]7"
19	// ppc64x:"ROTL\t[$]7"
20	// loong64: "ROTRV\t[$]57"
21	// riscv64: "RORI\t[$]57"
22	a += x<<7 | x>>57
23
24	// amd64:"ROLQ\t[$]8"
25	// arm64:"ROR\t[$]56"
26	// s390x:"RISBGZ\t[$]0, [$]63, [$]8, "
27	// ppc64x:"ROTL\t[$]8"
28	// loong64: "ROTRV\t[$]56"
29	// riscv64: "RORI\t[$]56"
30	a += x<<8 + x>>56
31
32	// amd64:"ROLQ\t[$]9"
33	// arm64:"ROR\t[$]55"
34	// s390x:"RISBGZ\t[$]0, [$]63, [$]9, "
35	// ppc64x:"ROTL\t[$]9"
36	// loong64: "ROTRV\t[$]55"
37	// riscv64: "RORI\t[$]55"
38	a += x<<9 ^ x>>55
39
40	// amd64:"ROLQ\t[$]10"
41	// arm64:"ROR\t[$]54"
42	// s390x:"RISBGZ\t[$]0, [$]63, [$]10, "
43	// ppc64x:"ROTL\t[$]10"
44	// arm64:"ROR\t[$]54"
45	// s390x:"RISBGZ\t[$]0, [$]63, [$]10, "
46	// loong64: "ROTRV\t[$]54"
47	// riscv64: "RORI\t[$]54"
48	a += bits.RotateLeft64(x, 10)
49
50	return a
51}
52
53func rot32(x uint32) uint32 {
54	var a uint32
55
56	// amd64:"ROLL\t[$]7"
57	// arm:"MOVW\tR\\d+@>25"
58	// ppc64x:"ROTLW\t[$]7"
59	// loong64: "ROTR\t[$]25"
60	// riscv64: "RORIW\t[$]25"
61	a += x<<7 | x>>25
62
63	// amd64:`ROLL\t[$]8`
64	// arm:"MOVW\tR\\d+@>24"
65	// arm64:"RORW\t[$]24"
66	// s390x:"RLL\t[$]8"
67	// ppc64x:"ROTLW\t[$]8"
68	// loong64: "ROTR\t[$]24"
69	// riscv64: "RORIW\t[$]24"
70	a += x<<8 + x>>24
71
72	// amd64:"ROLL\t[$]9"
73	// arm:"MOVW\tR\\d+@>23"
74	// arm64:"RORW\t[$]23"
75	// s390x:"RLL\t[$]9"
76	// ppc64x:"ROTLW\t[$]9"
77	// loong64: "ROTR\t[$]23"
78	// riscv64: "RORIW\t[$]23"
79	a += x<<9 ^ x>>23
80
81	// amd64:"ROLL\t[$]10"
82	// arm:"MOVW\tR\\d+@>22"
83	// arm64:"RORW\t[$]22"
84	// s390x:"RLL\t[$]10"
85	// ppc64x:"ROTLW\t[$]10"
86	// arm64:"RORW\t[$]22"
87	// s390x:"RLL\t[$]10"
88	// loong64: "ROTR\t[$]22"
89	// riscv64: "RORIW\t[$]22"
90	a += bits.RotateLeft32(x, 10)
91
92	return a
93}
94
95func rot16(x uint16) uint16 {
96	var a uint16
97
98	// amd64:"ROLW\t[$]7"
99	// riscv64: "OR","SLLI","SRLI",-"AND"
100	a += x<<7 | x>>9
101
102	// amd64:`ROLW\t[$]8`
103	// riscv64: "OR","SLLI","SRLI",-"AND"
104	a += x<<8 + x>>8
105
106	// amd64:"ROLW\t[$]9"
107	// riscv64: "OR","SLLI","SRLI",-"AND"
108	a += x<<9 ^ x>>7
109
110	return a
111}
112
113func rot8(x uint8) uint8 {
114	var a uint8
115
116	// amd64:"ROLB\t[$]5"
117	// riscv64: "OR","SLLI","SRLI",-"AND"
118	a += x<<5 | x>>3
119
120	// amd64:`ROLB\t[$]6`
121	// riscv64: "OR","SLLI","SRLI",-"AND"
122	a += x<<6 + x>>2
123
124	// amd64:"ROLB\t[$]7"
125	// riscv64: "OR","SLLI","SRLI",-"AND"
126	a += x<<7 ^ x>>1
127
128	return a
129}
130
131// ----------------------- //
132//    non-const rotates    //
133// ----------------------- //
134
135func rot64nc(x uint64, z uint) uint64 {
136	var a uint64
137
138	z &= 63
139
140	// amd64:"ROLQ",-"AND"
141	// arm64:"ROR","NEG",-"AND"
142	// ppc64x:"ROTL",-"NEG",-"AND"
143	// loong64: "ROTRV", -"AND"
144	// riscv64: "ROL",-"AND"
145	a += x<<z | x>>(64-z)
146
147	// amd64:"RORQ",-"AND"
148	// arm64:"ROR",-"NEG",-"AND"
149	// ppc64x:"ROTL","NEG",-"AND"
150	// loong64: "ROTRV", -"AND"
151	// riscv64: "ROR",-"AND"
152	a += x>>z | x<<(64-z)
153
154	return a
155}
156
157func rot32nc(x uint32, z uint) uint32 {
158	var a uint32
159
160	z &= 31
161
162	// amd64:"ROLL",-"AND"
163	// arm64:"ROR","NEG",-"AND"
164	// ppc64x:"ROTLW",-"NEG",-"AND"
165	// loong64: "ROTR", -"AND"
166	// riscv64: "ROLW",-"AND"
167	a += x<<z | x>>(32-z)
168
169	// amd64:"RORL",-"AND"
170	// arm64:"ROR",-"NEG",-"AND"
171	// ppc64x:"ROTLW","NEG",-"AND"
172	// loong64: "ROTR", -"AND"
173	// riscv64: "RORW",-"AND"
174	a += x>>z | x<<(32-z)
175
176	return a
177}
178
179func rot16nc(x uint16, z uint) uint16 {
180	var a uint16
181
182	z &= 15
183
184	// amd64:"ROLW",-"ANDQ"
185	// riscv64: "OR","SLL","SRL",-"AND\t"
186	a += x<<z | x>>(16-z)
187
188	// amd64:"RORW",-"ANDQ"
189	// riscv64: "OR","SLL","SRL",-"AND\t"
190	a += x>>z | x<<(16-z)
191
192	return a
193}
194
195func rot8nc(x uint8, z uint) uint8 {
196	var a uint8
197
198	z &= 7
199
200	// amd64:"ROLB",-"ANDQ"
201	// riscv64: "OR","SLL","SRL",-"AND\t"
202	a += x<<z | x>>(8-z)
203
204	// amd64:"RORB",-"ANDQ"
205	// riscv64: "OR","SLL","SRL",-"AND\t"
206	a += x>>z | x<<(8-z)
207
208	return a
209}
210
211// Issue 18254: rotate after inlining
212func f32(x uint32) uint32 {
213	// amd64:"ROLL\t[$]7"
214	return rot32nc(x, 7)
215}
216
217func doubleRotate(x uint64) uint64 {
218	x = (x << 5) | (x >> 59)
219	// amd64:"ROLQ\t[$]15"
220	// arm64:"ROR\t[$]49"
221	x = (x << 10) | (x >> 54)
222	return x
223}
224
225// --------------------------------------- //
226//    Combined Rotate + Masking operations //
227// --------------------------------------- //
228
229func checkMaskedRotate32(a []uint32, r int) {
230	i := 0
231
232	// ppc64x: "RLWNM\t[$]16, R[0-9]+, [$]8, [$]15, R[0-9]+"
233	a[i] = bits.RotateLeft32(a[i], 16) & 0xFF0000
234	i++
235	// ppc64x: "RLWNM\t[$]16, R[0-9]+, [$]8, [$]15, R[0-9]+"
236	a[i] = bits.RotateLeft32(a[i]&0xFF, 16)
237	i++
238	// ppc64x: "RLWNM\t[$]4, R[0-9]+, [$]20, [$]27, R[0-9]+"
239	a[i] = bits.RotateLeft32(a[i], 4) & 0xFF0
240	i++
241	// ppc64x: "RLWNM\t[$]16, R[0-9]+, [$]24, [$]31, R[0-9]+"
242	a[i] = bits.RotateLeft32(a[i]&0xFF0000, 16)
243	i++
244
245	// ppc64x: "RLWNM\tR[0-9]+, R[0-9]+, [$]8, [$]15, R[0-9]+"
246	a[i] = bits.RotateLeft32(a[i], r) & 0xFF0000
247	i++
248	// ppc64x: "RLWNM\tR[0-9]+, R[0-9]+, [$]16, [$]23, R[0-9]+"
249	a[i] = bits.RotateLeft32(a[i], r) & 0xFF00
250	i++
251
252	// ppc64x: "RLWNM\tR[0-9]+, R[0-9]+, [$]20, [$]11, R[0-9]+"
253	a[i] = bits.RotateLeft32(a[i], r) & 0xFFF00FFF
254	i++
255	// ppc64x: "RLWNM\t[$]4, R[0-9]+, [$]20, [$]11, R[0-9]+"
256	a[i] = bits.RotateLeft32(a[i], 4) & 0xFFF00FFF
257	i++
258}
259
260// combined arithmetic and rotate on arm64
261func checkArithmeticWithRotate(a *[1000]uint64) {
262	// arm64: "AND\tR[0-9]+@>51, R[0-9]+, R[0-9]+"
263	a[2] = a[1] & bits.RotateLeft64(a[0], 13)
264	// arm64: "ORR\tR[0-9]+@>51, R[0-9]+, R[0-9]+"
265	a[5] = a[4] | bits.RotateLeft64(a[3], 13)
266	// arm64: "EOR\tR[0-9]+@>51, R[0-9]+, R[0-9]+"
267	a[8] = a[7] ^ bits.RotateLeft64(a[6], 13)
268	// arm64: "MVN\tR[0-9]+@>51, R[0-9]+"
269	a[10] = ^bits.RotateLeft64(a[9], 13)
270	// arm64: "BIC\tR[0-9]+@>51, R[0-9]+, R[0-9]+"
271	a[13] = a[12] &^ bits.RotateLeft64(a[11], 13)
272	// arm64: "EON\tR[0-9]+@>51, R[0-9]+, R[0-9]+"
273	a[16] = a[15] ^ ^bits.RotateLeft64(a[14], 13)
274	// arm64: "ORN\tR[0-9]+@>51, R[0-9]+, R[0-9]+"
275	a[19] = a[18] | ^bits.RotateLeft64(a[17], 13)
276	// arm64: "TST\tR[0-9]+@>51, R[0-9]+"
277	if a[18]&bits.RotateLeft64(a[19], 13) == 0 {
278		a[20] = 1
279	}
280
281}
282