freedreno/cffdump: add arg to filter by process name
[mesa.git] / src / freedreno / computerator / examples / test-opcodes.sh
1 #!/bin/bash
2 #
3 # Test various instructions to check whether half<->full widening/narrowing
4 # works. The basic premise is to perform the same instruction with and
5 # without the widening/narrowing folded in and check if the results match.
6 #
7 # Note this doesn't currently diferentiate between signed/unsigned/bool,
8 # and just assumes int is signed (since unsigned is basically(ish) like
9 # signed but without sign extension)
10 #
11 # TODO probably good pick numeric src values that are better at triggering
12 # edge cases, while still not loosing precision in a full->half->full
13 # seqeuence.. but some instructions like absneg don't even appear to be
14 # subtlely wrong when you try to fold in a precision conversion.
15 #
16 # add '-v' arg to see the result values
17
18 set -e
19
20 #
21 # Templates for float->float instructions:
22 #
23 f2f_instrs=(
24 'add.f $dst, $src1, $src2'
25 'min.f $dst, $src1, $src2'
26 'min.f $dst, $src2, $src1'
27 'max.f $dst, $src1, $src2'
28 'max.f $dst, $src2, $src1'
29 'mul.f $dst, $src1, $src2'
30 'sign.f $dst, $src1'
31 'absneg.f $dst, \(neg\)$src1'
32 'absneg.f $dst, \(abs\)$src1'
33 'floor.f $dst, $src1'
34 'ceil.f $dst, $src1'
35 'rndne.f $dst, $src1'
36 'rndaz.f $dst, $src1'
37 'trunc.f $dst, $src1'
38 )
39
40 #
41 # Templates for float->int instructions:
42 #
43 f2i_instrs=(
44 'cmps.f.gt $dst, $src1, $src2'
45 'cmps.f.lt $dst, $src1, $src2'
46 'cmpv.f.gt $dst, $src1, $src2'
47 'cmpv.f.lt $dst, $src1, $src2'
48 )
49
50 #
51 # Templates for int->int instructions:
52 #
53 i2i_instrs=(
54 'add.u $dst, $src1, $src2'
55 'add.s $dst, $src1, $src2'
56 'sub.u $dst, $src1, $src2'
57 'sub.s $dst, $src1, $src2'
58 'cmps.f.gt $dst, $src1, $src2'
59 'cmps.f.lt $dst, $src1, $src2'
60 'min.u $dst, $src1, $src2'
61 'min.u $dst, $src2, $src1'
62 'min.s $dst, $src1, $src2'
63 'min.s $dst, $src2, $src1'
64 'max.u $dst, $src1, $src2'
65 'max.u $dst, $src2, $src1'
66 'max.s $dst, $src1, $src2'
67 'max.s $dst, $src2, $src1'
68 'absneg.s $dst, \(neg\)$src1'
69 'absneg.s $dst, \(abs\)$src1'
70 'and.b $dst, $src2, $src3'
71 'or.b $dst, $src1, $src2'
72 'not.b $dst, $src1'
73 'xor.b $dst, $src1, $src2'
74 'cmpv.u.gt $dst, $src1, $src2'
75 'cmpv.u.lt $dst, $src1, $src2'
76 'cmpv.s.gt $dst, $src1, $src2'
77 'cmpv.s.lt $dst, $src1, $src2'
78 'mul.u24 $dst, $src1, $src2'
79 'mul.s24 $dst, $src1, $src2'
80 'mull.u $dst, $src1, $src2'
81 'bfrev.b $dst, $src1'
82 'clz.s $dst, $src2'
83 'clz.b $dst, $src2'
84 'shl.b $dst, $src1, $src2'
85 'shr.b $dst, $src3, $src1'
86 'ashr.b $dst, $src3, $src1'
87 'mgen.b $dst, $src1, $src2'
88 'getbit.b $dst, $src3, $src2'
89 'setrm $dst, $src1'
90 'cbits.b $dst, $src3'
91 'shb $dst, $src1, $src2'
92 'msad $dst, $src1, $src2'
93 )
94
95 #
96 # Helper to expand instruction template:
97 #
98 expand() {
99 instr=$1
100 dst=$2
101 src1=$3
102 src2=$4
103 src3=$5
104 eval echo $instr
105 }
106
107 expand_test() {
108 instr=$1
109
110 echo '; control, half->half:'
111 expand $instr "hr1.x" "hr0.x" "hr0.y" "hr0.z"
112 echo '; test, full->half:'
113 expand $instr "hr1.y" "r1.x" "r1.y" "r1.z"
114
115 echo '; control, full->full:'
116 expand $instr "r2.x" "r1.x" "r1.y" "r1.z"
117 echo '; test, half->full:'
118 expand $instr "r2.y" "hr0.x" "hr0.y" "hr0.z"
119
120 echo "(rpt5)nop"
121 }
122
123 #
124 # Helpers to construct test program assembly:
125 #
126 header_asm() {
127 cat <<EOF
128 @localsize 1, 1, 1
129 @buf 4 ; g[0]
130 EOF
131 }
132
133 footer_asm() {
134 cat <<EOF
135 ; dest offsets:
136 mov.u32u32 r3.x, 0
137 mov.u32u32 r3.y, 1
138 mov.u32u32 r3.z, 2
139 mov.u32u32 r3.w, 3
140 (rpt5)nop
141
142 ; and store results:
143 stib.untyped.1d.u32.1 g[0] + r3.x, r2.x ; control: full->full
144 stib.untyped.1d.u32.1 g[0] + r3.y, r2.y ; test: half->full
145 stib.untyped.1d.u32.1 g[0] + r3.z, r2.z ; control: half->half
146 stib.untyped.1d.u32.1 g[0] + r3.w, r2.w ; test: full->half
147 (sy)nop
148 end
149 EOF
150 }
151
152 setup_asm_float() {
153 cat <<EOF
154 ; hr0->hr1 (r0) avail for half, hr0 for src, hr1 for dst
155 ; r1->r2 avail for full, r1 for src, r2 for dst
156 cov.f32f16 hr0.x, (1.0)
157 cov.f32f16 hr0.y, (2.0)
158 cov.f32f16 hr0.z, (3.0)
159 mov.f32f32 r1.x, (1.0)
160 mov.f32f32 r1.y, (2.0)
161 mov.f32f32 r1.z, (3.0)
162 (rpt5)nop
163 EOF
164 }
165
166 setup_asm_int() {
167 cat <<EOF
168 ; hr0->hr1 (r0) avail for half, hr0 for src, hr1 for dst
169 ; r1->r2 avail for full, r1 for src, r2 for dst
170 cov.s32s16 hr0.x, 1
171 cov.s32s16 hr0.y, -2
172 cov.s32s16 hr0.z, 3
173 mov.s32s32 r1.x, 1
174 mov.s32s32 r1.y, -2
175 mov.s32s32 r1.z, 3
176 (rpt5)nop
177 EOF
178 }
179
180 #
181 # Generate assembly code to test float->float opcode
182 #
183 f2f_asm() {
184 instr=$1
185
186 header_asm
187 setup_asm_float
188 expand_test $instr
189
190 cat <<EOF
191 ; convert half results back to full:
192 cov.f16f32 r2.z, hr1.x
193 cov.f16f32 r2.w, hr1.y
194 EOF
195
196 footer_asm
197 }
198
199 #
200 # Generate assembly code to test float->int opcode
201 #
202 f2i_asm() {
203 instr=$1
204
205 header_asm
206 setup_asm_float
207 expand_test $instr
208
209 cat <<EOF
210 ; convert half results back to full:
211 cov.s16s32 r2.z, hr1.x
212 cov.s16s32 r2.w, hr1.y
213 EOF
214
215 footer_asm
216 }
217
218 #
219 # Generate assembly code to test int->int opcode
220 #
221 i2i_asm() {
222 instr=$1
223
224 header_asm
225 setup_asm_int
226 expand_test $instr
227
228 cat <<EOF
229 ; convert half results back to full:
230 cov.s16s32 r2.z, hr1.x
231 cov.s16s32 r2.w, hr1.y
232 EOF
233
234 footer_asm
235 }
236
237
238 #
239 # Helper to parse computerator output and print results:
240 #
241 check_results() {
242 str=`cat - | grep " " | head -1 | xargs`
243
244 if [ "$verbose" = "true" ]; then
245 echo $str
246 fi
247
248 # Split components of result buffer:
249 cf=$(echo $str | cut -f1 -d' ')
250 tf=$(echo $str | cut -f2 -d' ')
251 ch=$(echo $str | cut -f3 -d' ')
252 th=$(echo $str | cut -f4 -d' ')
253
254 # Sanity test, make sure the control results match:
255 if [ $cf != $ch ]; then
256 echo " FAIL: control results do not match! Half vs full op is not equivalent!"
257 echo " full=$cf half=$ch"
258 fi
259
260 # Compare test (with conversion folded) to control:
261 if [ $cf != $tf ]; then
262 echo " FAIL: half -> full widening result does not match control!"
263 echo " control=$cf result=$tf"
264 fi
265 if [ $ch != $th ]; then
266 echo " FAIL: full -> half narrowing result does not match control!"
267 echo " control=$ch result=$th"
268 fi
269
270 # HACK without a delay different invocations
271 # of computerator seem to somehow clobber each
272 # other.. which isn't great..
273 sleep 0.1
274 }
275
276 #
277 # Run the tests!
278 #
279
280 if [ "$1" = "-v" ]; then
281 verbose="true"
282 fi
283
284 IFS=""
285 for instr in ${f2f_instrs[@]}; do
286 echo "TEST: $instr"
287 f2f_asm $instr | ./computerator -g 1,1,1 | check_results
288 done
289 for instr in ${f2i_instrs[@]}; do
290 echo "TEST: $instr"
291 f2i_asm $instr | ./computerator -g 1,1,1 | check_results
292 done
293 for instr in ${i2i_instrs[@]}; do
294 echo "TEST: $instr"
295 i2i_asm $instr | ./computerator -g 1,1,1 | check_results
296 done
297