xref: /openbmc/qemu/tests/tcg/hexagon/multi_result.c (revision 6016b7b4)
1 /*
2  *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <stdio.h>
19 
20 static int sfrecipa(int Rs, int Rt, int *pred_result)
21 {
22   int result;
23   int predval;
24 
25   asm volatile("%0,p0 = sfrecipa(%2, %3)\n\t"
26                "%1 = p0\n\t"
27                : "+r"(result), "=r"(predval)
28                : "r"(Rs), "r"(Rt)
29                : "p0");
30   *pred_result = predval;
31   return result;
32 }
33 
34 static int sfinvsqrta(int Rs, int *pred_result)
35 {
36   int result;
37   int predval;
38 
39   asm volatile("%0,p0 = sfinvsqrta(%2)\n\t"
40                "%1 = p0\n\t"
41                : "+r"(result), "=r"(predval)
42                : "r"(Rs)
43                : "p0");
44   *pred_result = predval;
45   return result;
46 }
47 
48 static long long vacsh(long long Rxx, long long Rss, long long Rtt,
49                        int *pred_result, int *ovf_result)
50 {
51   long long result = Rxx;
52   int predval;
53   int usr;
54 
55   /*
56    * This instruction can set bit 0 (OVF/overflow) in usr
57    * Clear the bit first, then return that bit to the caller
58    */
59   asm volatile("r2 = usr\n\t"
60                "r2 = clrbit(r2, #0)\n\t"        /* clear overflow bit */
61                "usr = r2\n\t"
62                "%0,p0 = vacsh(%3, %4)\n\t"
63                "%1 = p0\n\t"
64                "%2 = usr\n\t"
65                : "+r"(result), "=r"(predval), "=r"(usr)
66                : "r"(Rss), "r"(Rtt)
67                : "r2", "p0", "usr");
68   *pred_result = predval;
69   *ovf_result = (usr & 1);
70   return result;
71 }
72 
73 static long long vminub(long long Rtt, long long Rss,
74                         int *pred_result)
75 {
76   long long result;
77   int predval;
78 
79   asm volatile("%0,p0 = vminub(%2, %3)\n\t"
80                "%1 = p0\n\t"
81                : "=r"(result), "=r"(predval)
82                : "r"(Rtt), "r"(Rss)
83                : "p0");
84   *pred_result = predval;
85   return result;
86 }
87 
88 static long long add_carry(long long Rss, long long Rtt,
89                            int pred_in, int *pred_result)
90 {
91   long long result;
92   int predval = pred_in;
93 
94   asm volatile("p0 = %1\n\t"
95                "%0 = add(%2, %3, p0):carry\n\t"
96                "%1 = p0\n\t"
97                : "=r"(result), "+r"(predval)
98                : "r"(Rss), "r"(Rtt)
99                : "p0");
100   *pred_result = predval;
101   return result;
102 }
103 
104 static long long sub_carry(long long Rss, long long Rtt,
105                            int pred_in, int *pred_result)
106 {
107   long long result;
108   int predval = pred_in;
109 
110   asm volatile("p0 = !cmp.eq(%1, #0)\n\t"
111                "%0 = sub(%2, %3, p0):carry\n\t"
112                "%1 = p0\n\t"
113                : "=r"(result), "+r"(predval)
114                : "r"(Rss), "r"(Rtt)
115                : "p0");
116   *pred_result = predval;
117   return result;
118 }
119 
120 int err;
121 
122 static void check_ll(long long val, long long expect)
123 {
124     if (val != expect) {
125         printf("ERROR: 0x%016llx != 0x%016llx\n", val, expect);
126         err++;
127     }
128 }
129 
130 static void check(int val, int expect)
131 {
132     if (val != expect) {
133         printf("ERROR: 0x%08x != 0x%08x\n", val, expect);
134         err++;
135     }
136 }
137 
138 static void check_p(int val, int expect)
139 {
140     if (val != expect) {
141         printf("ERROR: 0x%02x != 0x%02x\n", val, expect);
142         err++;
143     }
144 }
145 
146 static void test_sfrecipa()
147 {
148     int res;
149     int pred_result;
150 
151     res = sfrecipa(0x04030201, 0x05060708, &pred_result);
152     check(res, 0x59f38001);
153     check_p(pred_result, 0x00);
154 }
155 
156 static void test_sfinvsqrta()
157 {
158     int res;
159     int pred_result;
160 
161     res = sfinvsqrta(0x04030201, &pred_result);
162     check(res, 0x4d330000);
163     check_p(pred_result, 0xe0);
164 
165     res = sfinvsqrta(0x0, &pred_result);
166     check(res, 0x3f800000);
167     check_p(pred_result, 0x0);
168 }
169 
170 static void test_vacsh()
171 {
172     long long res64;
173     int pred_result;
174     int ovf_result;
175 
176     res64 = vacsh(0x0004000300020001LL,
177                   0x0001000200030004LL,
178                   0x0000000000000000LL, &pred_result, &ovf_result);
179     check_ll(res64, 0x0004000300030004LL);
180     check_p(pred_result, 0xf0);
181     check(ovf_result, 0);
182 
183     res64 = vacsh(0x0004000300020001LL,
184                   0x0001000200030004LL,
185                   0x000affff000d0000LL, &pred_result, &ovf_result);
186     check_ll(res64, 0x000e0003000f0004LL);
187     check_p(pred_result, 0xcc);
188     check(ovf_result, 0);
189 
190     res64 = vacsh(0x00047fff00020001LL,
191                   0x00017fff00030004LL,
192                   0x000a0fff000d0000LL, &pred_result, &ovf_result);
193     check_ll(res64, 0x000e7fff000f0004LL);
194     check_p(pred_result, 0xfc);
195     check(ovf_result, 1);
196 
197     res64 = vacsh(0x0004000300020001LL,
198                   0x0001000200030009LL,
199                   0x000affff000d0001LL, &pred_result, &ovf_result);
200     check_ll(res64, 0x000e0003000f0008LL);
201     check_p(pred_result, 0xcc);
202     check(ovf_result, 0);
203 }
204 
205 static void test_vminub()
206 {
207     long long res64;
208     int pred_result;
209 
210     res64 = vminub(0x0807060504030201LL,
211                    0x0102030405060708LL,
212                    &pred_result);
213     check_ll(res64, 0x0102030404030201LL);
214     check_p(pred_result, 0xf0);
215 
216     res64 = vminub(0x0802060405030701LL,
217                    0x0107030504060208LL,
218                    &pred_result);
219     check_ll(res64, 0x0102030404030201LL);
220     check_p(pred_result, 0xaa);
221 }
222 
223 static void test_add_carry()
224 {
225     long long res64;
226     int pred_result;
227 
228     res64 = add_carry(0x0000000000000000LL,
229                       0xffffffffffffffffLL,
230                       1, &pred_result);
231     check_ll(res64, 0x0000000000000000LL);
232     check_p(pred_result, 0xff);
233 
234     res64 = add_carry(0x0000000100000000LL,
235                       0xffffffffffffffffLL,
236                       0, &pred_result);
237     check_ll(res64, 0x00000000ffffffffLL);
238     check_p(pred_result, 0xff);
239 
240     res64 = add_carry(0x0000000100000000LL,
241                       0xffffffffffffffffLL,
242                       0, &pred_result);
243     check_ll(res64, 0x00000000ffffffffLL);
244     check_p(pred_result, 0xff);
245 }
246 
247 static void test_sub_carry()
248 {
249     long long res64;
250     int pred_result;
251 
252     res64 = sub_carry(0x0000000000000000LL,
253                       0x0000000000000000LL,
254                       1, &pred_result);
255     check_ll(res64, 0x0000000000000000LL);
256     check_p(pred_result, 0xff);
257 
258     res64 = sub_carry(0x0000000100000000LL,
259                       0x0000000000000000LL,
260                       0, &pred_result);
261     check_ll(res64, 0x00000000ffffffffLL);
262     check_p(pred_result, 0xff);
263 
264     res64 = sub_carry(0x0000000100000000LL,
265                       0x0000000000000000LL,
266                       0, &pred_result);
267     check_ll(res64, 0x00000000ffffffffLL);
268     check_p(pred_result, 0xff);
269 }
270 
271 int main()
272 {
273     test_sfrecipa();
274     test_sfinvsqrta();
275     test_vacsh();
276     test_vminub();
277     test_add_carry();
278     test_sub_carry();
279 
280     puts(err ? "FAIL" : "PASS");
281     return err;
282 }
283