]> Cypherpunks.ru repositories - gostls13.git/blob - test/codegen/shift.go
bf8b63390553bb872c0fb5c24d458099f149a9e8
[gostls13.git] / test / codegen / shift.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 // ------------------ //
10 //   constant shifts  //
11 // ------------------ //
12
13 func lshConst64x64(v int64) int64 {
14         // ppc64x:"SLD"
15         // riscv64:"SLLI",-"AND",-"SLTIU"
16         return v << uint64(33)
17 }
18
19 func rshConst64Ux64(v uint64) uint64 {
20         // ppc64x:"SRD"
21         // riscv64:"SRLI\t",-"AND",-"SLTIU"
22         return v >> uint64(33)
23 }
24
25 func rshConst64x64(v int64) int64 {
26         // ppc64x:"SRAD"
27         // riscv64:"SRAI",-"OR",-"SLTIU"
28         return v >> uint64(33)
29 }
30
31 func lshConst32x64(v int32) int32 {
32         // ppc64x:"SLW"
33         // riscv64:"SLLI",-"AND",-"SLTIU", -"MOVW"
34         return v << uint64(29)
35 }
36
37 func rshConst32Ux64(v uint32) uint32 {
38         // ppc64x:"SRW"
39         // riscv64:"SRLIW",-"AND",-"SLTIU", -"MOVW"
40         return v >> uint64(29)
41 }
42
43 func rshConst32x64(v int32) int32 {
44         // ppc64x:"SRAW"
45         // riscv64:"SRAI",-"OR",-"SLTIU", -"MOVW"
46         return v >> uint64(29)
47 }
48
49 func lshConst64x32(v int64) int64 {
50         // ppc64x:"SLD"
51         // riscv64:"SLLI",-"AND",-"SLTIU"
52         return v << uint32(33)
53 }
54
55 func rshConst64Ux32(v uint64) uint64 {
56         // ppc64x:"SRD"
57         // riscv64:"SRLI\t",-"AND",-"SLTIU"
58         return v >> uint32(33)
59 }
60
61 func rshConst64x32(v int64) int64 {
62         // ppc64x:"SRAD"
63         // riscv64:"SRAI",-"OR",-"SLTIU"
64         return v >> uint32(33)
65 }
66
67 // ------------------ //
68 //   masked shifts    //
69 // ------------------ //
70
71 func lshMask64x64(v int64, s uint64) int64 {
72         // arm64:"LSL",-"AND"
73         // ppc64x:"RLDICL",-"ORN",-"ISEL"
74         // riscv64:"SLL",-"AND\t",-"SLTIU"
75         // s390x:-"RISBGZ",-"AND",-"LOCGR"
76         return v << (s & 63)
77 }
78
79 func rshMask64Ux64(v uint64, s uint64) uint64 {
80         // arm64:"LSR",-"AND",-"CSEL"
81         // ppc64x:"RLDICL",-"ORN",-"ISEL"
82         // riscv64:"SRL\t",-"AND\t",-"SLTIU"
83         // s390x:-"RISBGZ",-"AND",-"LOCGR"
84         return v >> (s & 63)
85 }
86
87 func rshMask64x64(v int64, s uint64) int64 {
88         // arm64:"ASR",-"AND",-"CSEL"
89         // ppc64x:"RLDICL",-"ORN",-"ISEL"
90         // riscv64:"SRA",-"OR",-"SLTIU"
91         // s390x:-"RISBGZ",-"AND",-"LOCGR"
92         return v >> (s & 63)
93 }
94
95 func lshMask32x64(v int32, s uint64) int32 {
96         // arm64:"LSL",-"AND"
97         // ppc64x:"ISEL",-"ORN"
98         // riscv64:"SLL",-"AND\t",-"SLTIU"
99         // s390x:-"RISBGZ",-"AND",-"LOCGR"
100         return v << (s & 63)
101 }
102
103 func rshMask32Ux64(v uint32, s uint64) uint32 {
104         // arm64:"LSR",-"AND"
105         // ppc64x:"ISEL",-"ORN"
106         // riscv64:"SRLW","SLTIU","NEG","AND\t",-"SRL\t"
107         // s390x:-"RISBGZ",-"AND",-"LOCGR"
108         return v >> (s & 63)
109 }
110
111 func rsh5Mask32Ux64(v uint32, s uint64) uint32 {
112         // riscv64:"SRLW",-"AND\t",-"SLTIU",-"SRL\t"
113         return v >> (s & 31)
114 }
115
116 func rshMask32x64(v int32, s uint64) int32 {
117         // arm64:"ASR",-"AND"
118         // ppc64x:"ISEL",-"ORN"
119         // riscv64:"SRA",-"OR",-"SLTIU"
120         // s390x:-"RISBGZ",-"AND",-"LOCGR"
121         return v >> (s & 63)
122 }
123
124 func lshMask64x32(v int64, s uint32) int64 {
125         // arm64:"LSL",-"AND"
126         // ppc64x:"RLDICL",-"ORN"
127         // riscv64:"SLL",-"AND\t",-"SLTIU"
128         // s390x:-"RISBGZ",-"AND",-"LOCGR"
129         return v << (s & 63)
130 }
131
132 func rshMask64Ux32(v uint64, s uint32) uint64 {
133         // arm64:"LSR",-"AND",-"CSEL"
134         // ppc64x:"RLDICL",-"ORN"
135         // riscv64:"SRL\t",-"AND\t",-"SLTIU"
136         // s390x:-"RISBGZ",-"AND",-"LOCGR"
137         return v >> (s & 63)
138 }
139
140 func rshMask64x32(v int64, s uint32) int64 {
141         // arm64:"ASR",-"AND",-"CSEL"
142         // ppc64x:"RLDICL",-"ORN",-"ISEL"
143         // riscv64:"SRA",-"OR",-"SLTIU"
144         // s390x:-"RISBGZ",-"AND",-"LOCGR"
145         return v >> (s & 63)
146 }
147
148 func lshMask64x32Ext(v int64, s int32) int64 {
149         // ppc64x:"RLDICL",-"ORN",-"ISEL"
150         // riscv64:"SLL",-"AND\t",-"SLTIU"
151         // s390x:-"RISBGZ",-"AND",-"LOCGR"
152         return v << uint(s&63)
153 }
154
155 func rshMask64Ux32Ext(v uint64, s int32) uint64 {
156         // ppc64x:"RLDICL",-"ORN",-"ISEL"
157         // riscv64:"SRL\t",-"AND\t",-"SLTIU"
158         // s390x:-"RISBGZ",-"AND",-"LOCGR"
159         return v >> uint(s&63)
160 }
161
162 func rshMask64x32Ext(v int64, s int32) int64 {
163         // ppc64x:"RLDICL",-"ORN",-"ISEL"
164         // riscv64:"SRA",-"OR",-"SLTIU"
165         // s390x:-"RISBGZ",-"AND",-"LOCGR"
166         return v >> uint(s&63)
167 }
168
169 // --------------- //
170 //  signed shifts  //
171 // --------------- //
172
173 // We do want to generate a test + panicshift for these cases.
174 func lshSigned(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
175         // amd64:"TESTB"
176         _ = x << v8
177         // amd64:"TESTW"
178         _ = x << v16
179         // amd64:"TESTL"
180         _ = x << v32
181         // amd64:"TESTQ"
182         _ = x << v64
183 }
184
185 // We want to avoid generating a test + panicshift for these cases.
186 func lshSignedMasked(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
187         // amd64:-"TESTB"
188         _ = x << (v8 & 7)
189         // amd64:-"TESTW"
190         _ = x << (v16 & 15)
191         // amd64:-"TESTL"
192         _ = x << (v32 & 31)
193         // amd64:-"TESTQ"
194         _ = x << (v64 & 63)
195 }
196
197 // ------------------ //
198 //   bounded shifts   //
199 // ------------------ //
200
201 func lshGuarded64(v int64, s uint) int64 {
202         if s < 64 {
203                 // riscv64:"SLL",-"AND",-"SLTIU"
204                 // s390x:-"RISBGZ",-"AND",-"LOCGR"
205                 // wasm:-"Select",-".*LtU"
206                 // arm64:"LSL",-"CSEL"
207                 return v << s
208         }
209         panic("shift too large")
210 }
211
212 func rshGuarded64U(v uint64, s uint) uint64 {
213         if s < 64 {
214                 // riscv64:"SRL\t",-"AND",-"SLTIU"
215                 // s390x:-"RISBGZ",-"AND",-"LOCGR"
216                 // wasm:-"Select",-".*LtU"
217                 // arm64:"LSR",-"CSEL"
218                 return v >> s
219         }
220         panic("shift too large")
221 }
222
223 func rshGuarded64(v int64, s uint) int64 {
224         if s < 64 {
225                 // riscv64:"SRA",-"OR",-"SLTIU"
226                 // s390x:-"RISBGZ",-"AND",-"LOCGR"
227                 // wasm:-"Select",-".*LtU"
228                 // arm64:"ASR",-"CSEL"
229                 return v >> s
230         }
231         panic("shift too large")
232 }
233
234 func provedUnsignedShiftLeft(val64 uint64, val32 uint32, val16 uint16, val8 uint8, shift int) (r1 uint64, r2 uint32, r3 uint16, r4 uint8) {
235         if shift >= 0 && shift < 64 {
236                 // arm64:"LSL",-"CSEL"
237                 r1 = val64 << shift
238         }
239         if shift >= 0 && shift < 32 {
240                 // arm64:"LSL",-"CSEL"
241                 r2 = val32 << shift
242         }
243         if shift >= 0 && shift < 16 {
244                 // arm64:"LSL",-"CSEL"
245                 r3 = val16 << shift
246         }
247         if shift >= 0 && shift < 8 {
248                 // arm64:"LSL",-"CSEL"
249                 r4 = val8 << shift
250         }
251         return r1, r2, r3, r4
252 }
253
254 func provedSignedShiftLeft(val64 int64, val32 int32, val16 int16, val8 int8, shift int) (r1 int64, r2 int32, r3 int16, r4 int8) {
255         if shift >= 0 && shift < 64 {
256                 // arm64:"LSL",-"CSEL"
257                 r1 = val64 << shift
258         }
259         if shift >= 0 && shift < 32 {
260                 // arm64:"LSL",-"CSEL"
261                 r2 = val32 << shift
262         }
263         if shift >= 0 && shift < 16 {
264                 // arm64:"LSL",-"CSEL"
265                 r3 = val16 << shift
266         }
267         if shift >= 0 && shift < 8 {
268                 // arm64:"LSL",-"CSEL"
269                 r4 = val8 << shift
270         }
271         return r1, r2, r3, r4
272 }
273
274 func provedUnsignedShiftRight(val64 uint64, val32 uint32, val16 uint16, val8 uint8, shift int) (r1 uint64, r2 uint32, r3 uint16, r4 uint8) {
275         if shift >= 0 && shift < 64 {
276                 // arm64:"LSR",-"CSEL"
277                 r1 = val64 >> shift
278         }
279         if shift >= 0 && shift < 32 {
280                 // arm64:"LSR",-"CSEL"
281                 r2 = val32 >> shift
282         }
283         if shift >= 0 && shift < 16 {
284                 // arm64:"LSR",-"CSEL"
285                 r3 = val16 >> shift
286         }
287         if shift >= 0 && shift < 8 {
288                 // arm64:"LSR",-"CSEL"
289                 r4 = val8 >> shift
290         }
291         return r1, r2, r3, r4
292 }
293
294 func provedSignedShiftRight(val64 int64, val32 int32, val16 int16, val8 int8, shift int) (r1 int64, r2 int32, r3 int16, r4 int8) {
295         if shift >= 0 && shift < 64 {
296                 // arm64:"ASR",-"CSEL"
297                 r1 = val64 >> shift
298         }
299         if shift >= 0 && shift < 32 {
300                 // arm64:"ASR",-"CSEL"
301                 r2 = val32 >> shift
302         }
303         if shift >= 0 && shift < 16 {
304                 // arm64:"ASR",-"CSEL"
305                 r3 = val16 >> shift
306         }
307         if shift >= 0 && shift < 8 {
308                 // arm64:"ASR",-"CSEL"
309                 r4 = val8 >> shift
310         }
311         return r1, r2, r3, r4
312 }
313
314 func checkUnneededTrunc(tab *[100000]uint32, d uint64, v uint32, h uint16, b byte) (uint32, uint64) {
315
316         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
317         f := tab[byte(v)^b]
318         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
319         f += tab[byte(v)&b]
320         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
321         f += tab[byte(v)|b]
322         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
323         f += tab[uint16(v)&h]
324         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
325         f += tab[uint16(v)^h]
326         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
327         f += tab[uint16(v)|h]
328         // ppc64x:-".*AND",-"RLDICR",".*CLRLSLDI"
329         f += tab[v&0xff]
330         // ppc64x:-".*AND",".*CLRLSLWI"
331         f += 2 * uint32(uint16(d))
332         // ppc64x:-".*AND",-"RLDICR",".*CLRLSLDI"
333         g := 2 * uint64(uint32(d))
334         return f, g
335 }
336
337 func checkCombinedShifts(v8 uint8, v16 uint16, v32 uint32, x32 int32, v64 uint64) (uint8, uint16, uint32, uint64, int64) {
338
339         // ppc64x:-"AND","CLRLSLWI"
340         f := (v8 & 0xF) << 2
341         // ppc64x:"CLRLSLWI"
342         f += byte(v16) << 3
343         // ppc64x:-"AND","CLRLSLWI"
344         g := (v16 & 0xFF) << 3
345         // ppc64x:-"AND","CLRLSLWI"
346         h := (v32 & 0xFFFFF) << 2
347         // ppc64x:"CLRLSLDI"
348         i := (v64 & 0xFFFFFFFF) << 5
349         // ppc64x:-"CLRLSLDI"
350         i += (v64 & 0xFFFFFFF) << 38
351         // ppc64x/power9:-"CLRLSLDI"
352         i += (v64 & 0xFFFF00) << 10
353         // ppc64x/power9:-"SLD","EXTSWSLI"
354         j := int64(x32+32) * 8
355         return f, g, h, i, j
356 }
357
358 func checkWidenAfterShift(v int64, u uint64) (int64, uint64) {
359
360         // ppc64x:-".*MOVW"
361         f := int32(v >> 32)
362         // ppc64x:".*MOVW"
363         f += int32(v >> 31)
364         // ppc64x:-".*MOVH"
365         g := int16(v >> 48)
366         // ppc64x:".*MOVH"
367         g += int16(v >> 30)
368         // ppc64x:-".*MOVH"
369         g += int16(f >> 16)
370         // ppc64x:-".*MOVB"
371         h := int8(v >> 56)
372         // ppc64x:".*MOVB"
373         h += int8(v >> 28)
374         // ppc64x:-".*MOVB"
375         h += int8(f >> 24)
376         // ppc64x:".*MOVB"
377         h += int8(f >> 16)
378         return int64(h), uint64(g)
379 }
380
381 func checkShiftAndMask32(v []uint32) {
382         i := 0
383
384         // ppc64x: "RLWNM\t[$]24, R[0-9]+, [$]12, [$]19, R[0-9]+"
385         v[i] = (v[i] & 0xFF00000) >> 8
386         i++
387         // ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]22, [$]29, R[0-9]+"
388         v[i] = (v[i] & 0xFF00) >> 6
389         i++
390         // ppc64x: "MOVW\tR0"
391         v[i] = (v[i] & 0xFF) >> 8
392         i++
393         // ppc64x: "MOVW\tR0"
394         v[i] = (v[i] & 0xF000000) >> 28
395         i++
396         // ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]24, [$]31, R[0-9]+"
397         v[i] = (v[i] >> 6) & 0xFF
398         i++
399         // ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]12, [$]19, R[0-9]+"
400         v[i] = (v[i] >> 6) & 0xFF000
401         i++
402         // ppc64x: "MOVW\tR0"
403         v[i] = (v[i] >> 20) & 0xFF000
404         i++
405         // ppc64x: "MOVW\tR0"
406         v[i] = (v[i] >> 24) & 0xFF00
407         i++
408 }
409
410 func checkMergedShifts32(a [256]uint32, b [256]uint64, u uint32, v uint32) {
411         // ppc64x: -"CLRLSLDI", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]29, R[0-9]+"
412         a[0] = a[uint8(v>>24)]
413         // ppc64x: -"CLRLSLDI", "RLWNM\t[$]11, R[0-9]+, [$]21, [$]28, R[0-9]+"
414         b[0] = b[uint8(v>>24)]
415         // ppc64x: -"CLRLSLDI", "RLWNM\t[$]15, R[0-9]+, [$]21, [$]28, R[0-9]+"
416         b[1] = b[(v>>20)&0xFF]
417         // ppc64x: -"SLD", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]28, R[0-9]+"
418         b[2] = b[v>>25]
419 }
420
421 // 128 bit shifts
422
423 func check128bitShifts(x, y uint64, bits uint) (uint64, uint64) {
424         s := bits & 63
425         ŝ := (64 - bits) & 63
426         // check that the shift operation has two commas (three operands)
427         // amd64:"SHRQ.*,.*,"
428         shr := x>>s | y<<ŝ
429         // amd64:"SHLQ.*,.*,"
430         shl := x<<s | y>>ŝ
431         return shr, shl
432 }
433
434 func checkShiftToMask(u []uint64, s []int64) {
435         // amd64:-"SHR",-"SHL","ANDQ"
436         u[0] = u[0] >> 5 << 5
437         // amd64:-"SAR",-"SHL","ANDQ"
438         s[0] = s[0] >> 5 << 5
439         // amd64:-"SHR",-"SHL","ANDQ"
440         u[1] = u[1] << 5 >> 5
441 }