xref: /openbmc/qemu/tests/tcg/hexagon/multi_result.c (revision 7d87775f)
1 /*
2  *  Copyright(c) 2019-2023 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 #include <stdint.h>
20 #include <stdbool.h>
21 
22 int err;
23 
24 #include "hex_test.h"
25 
26 static int32_t sfrecipa(int32_t Rs, int32_t Rt, bool *pred_result)
27 {
28   int32_t result;
29   bool predval;
30 
31   asm volatile("%0,p0 = sfrecipa(%2, %3)\n\t"
32                "%1 = p0\n\t"
33                : "+r"(result), "=r"(predval)
34                : "r"(Rs), "r"(Rt)
35                : "p0");
36   *pred_result = predval;
37   return result;
38 }
39 
40 static int32_t sfinvsqrta(int32_t Rs, int32_t *pred_result)
41 {
42   int32_t result;
43   int32_t predval;
44 
45   asm volatile("%0,p0 = sfinvsqrta(%2)\n\t"
46                "%1 = p0\n\t"
47                : "+r"(result), "=r"(predval)
48                : "r"(Rs)
49                : "p0");
50   *pred_result = predval;
51   return result;
52 }
53 
54 static int64_t vacsh(int64_t Rxx, int64_t Rss, int64_t Rtt,
55                      int *pred_result, bool *ovf_result)
56 {
57   int64_t result = Rxx;
58   int predval;
59   uint32_t usr;
60 
61   /*
62    * This instruction can set bit 0 (OVF/overflow) in usr
63    * Clear the bit first, then return that bit to the caller
64    */
65   asm volatile("r2 = usr\n\t"
66                "r2 = clrbit(r2, #0)\n\t"        /* clear overflow bit */
67                "usr = r2\n\t"
68                "%0,p0 = vacsh(%3, %4)\n\t"
69                "%1 = p0\n\t"
70                "%2 = usr\n\t"
71                : "+r"(result), "=r"(predval), "=r"(usr)
72                : "r"(Rss), "r"(Rtt)
73                : "r2", "p0", "usr");
74   *pred_result = predval;
75   *ovf_result = (usr & 1);
76   return result;
77 }
78 
79 static int64_t vminub(int64_t Rtt, int64_t Rss, int32_t *pred_result)
80 {
81   int64_t result;
82   int32_t predval;
83 
84   asm volatile("%0,p0 = vminub(%2, %3)\n\t"
85                "%1 = p0\n\t"
86                : "=r"(result), "=r"(predval)
87                : "r"(Rtt), "r"(Rss)
88                : "p0");
89   *pred_result = predval;
90   return result;
91 }
92 
93 static int64_t add_carry(int64_t Rss, int64_t Rtt,
94                          int32_t pred_in, int32_t *pred_result)
95 {
96   int64_t result;
97   int32_t predval = pred_in;
98 
99   asm volatile("p0 = %1\n\t"
100                "%0 = add(%2, %3, p0):carry\n\t"
101                "%1 = p0\n\t"
102                : "=r"(result), "+r"(predval)
103                : "r"(Rss), "r"(Rtt)
104                : "p0");
105   *pred_result = predval;
106   return result;
107 }
108 
109 static int64_t sub_carry(int64_t Rss, int64_t Rtt,
110                          int32_t pred_in, int32_t *pred_result)
111 {
112   int64_t result;
113   int32_t predval = pred_in;
114 
115   asm volatile("p0 = !cmp.eq(%1, #0)\n\t"
116                "%0 = sub(%2, %3, p0):carry\n\t"
117                "%1 = p0\n\t"
118                : "=r"(result), "+r"(predval)
119                : "r"(Rss), "r"(Rtt)
120                : "p0");
121   *pred_result = predval;
122   return result;
123 }
124 
125 static void test_sfrecipa()
126 {
127     int32_t res;
128     bool pred_result;
129 
130     res = sfrecipa(0x04030201, 0x05060708, &pred_result);
131     check32(res, 0x59f38001);
132     check32(pred_result, false);
133 }
134 
135 static void test_sfinvsqrta()
136 {
137     int32_t res;
138     int32_t pred_result;
139 
140     res = sfinvsqrta(0x04030201, &pred_result);
141     check32(res, 0x4d330000);
142     check32(pred_result, 0xe0);
143 
144     res = sfinvsqrta(0x0, &pred_result);
145     check32(res, 0x3f800000);
146     check32(pred_result, 0x0);
147 }
148 
149 static void test_vacsh()
150 {
151     int64_t res64;
152     int32_t pred_result;
153     bool ovf_result;
154 
155     res64 = vacsh(0x0004000300020001LL,
156                   0x0001000200030004LL,
157                   0x0000000000000000LL, &pred_result, &ovf_result);
158     check64(res64, 0x0004000300030004LL);
159     check32(pred_result, 0xf0);
160     check32(ovf_result, false);
161 
162     res64 = vacsh(0x0004000300020001LL,
163                   0x0001000200030004LL,
164                   0x000affff000d0000LL, &pred_result, &ovf_result);
165     check64(res64, 0x000e0003000f0004LL);
166     check32(pred_result, 0xcc);
167     check32(ovf_result, false);
168 
169     res64 = vacsh(0x00047fff00020001LL,
170                   0x00017fff00030004LL,
171                   0x000a0fff000d0000LL, &pred_result, &ovf_result);
172     check64(res64, 0x000e7fff000f0004LL);
173     check32(pred_result, 0xfc);
174     check32(ovf_result, true);
175 
176     res64 = vacsh(0x0004000300020001LL,
177                   0x0001000200030009LL,
178                   0x000affff000d0001LL, &pred_result, &ovf_result);
179     check64(res64, 0x000e0003000f0008LL);
180     check32(pred_result, 0xcc);
181     check32(ovf_result, false);
182 }
183 
184 static void test_vminub()
185 {
186     int64_t res64;
187     int32_t pred_result;
188 
189     res64 = vminub(0x0807060504030201LL,
190                    0x0102030405060708LL,
191                    &pred_result);
192     check64(res64, 0x0102030404030201LL);
193     check32(pred_result, 0xf0);
194 
195     res64 = vminub(0x0802060405030701LL,
196                    0x0107030504060208LL,
197                    &pred_result);
198     check64(res64, 0x0102030404030201LL);
199     check32(pred_result, 0xaa);
200 }
201 
202 static void test_add_carry()
203 {
204     int64_t res64;
205     int32_t pred_result;
206 
207     res64 = add_carry(0x0000000000000000LL,
208                       0xffffffffffffffffLL,
209                       1, &pred_result);
210     check64(res64, 0x0000000000000000LL);
211     check32(pred_result, 0xff);
212 
213     res64 = add_carry(0x0000000100000000LL,
214                       0xffffffffffffffffLL,
215                       0, &pred_result);
216     check64(res64, 0x00000000ffffffffLL);
217     check32(pred_result, 0xff);
218 
219     res64 = add_carry(0x0000000100000000LL,
220                       0xffffffffffffffffLL,
221                       0, &pred_result);
222     check64(res64, 0x00000000ffffffffLL);
223     check32(pred_result, 0xff);
224 }
225 
226 static void test_sub_carry()
227 {
228     int64_t res64;
229     int32_t pred_result;
230 
231     res64 = sub_carry(0x0000000000000000LL,
232                       0x0000000000000000LL,
233                       1, &pred_result);
234     check64(res64, 0x0000000000000000LL);
235     check32(pred_result, 0xff);
236 
237     res64 = sub_carry(0x0000000100000000LL,
238                       0x0000000000000000LL,
239                       0, &pred_result);
240     check64(res64, 0x00000000ffffffffLL);
241     check32(pred_result, 0xff);
242 
243     res64 = sub_carry(0x0000000100000000LL,
244                       0x0000000000000000LL,
245                       0, &pred_result);
246     check64(res64, 0x00000000ffffffffLL);
247     check32(pred_result, 0xff);
248 }
249 
250 int main()
251 {
252     test_sfrecipa();
253     test_sfinvsqrta();
254     test_vacsh();
255     test_vminub();
256     test_add_carry();
257     test_sub_carry();
258 
259     puts(err ? "FAIL" : "PASS");
260     return err;
261 }
262