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
sfrecipa(int Rs,int Rt,int * pred_result)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
sfinvsqrta(int Rs,int * pred_result)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
vacsh(long long Rxx,long long Rss,long long Rtt,int * pred_result,int * ovf_result)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
vminub(long long Rtt,long long Rss,int * pred_result)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
add_carry(long long Rss,long long Rtt,int pred_in,int * pred_result)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
sub_carry(long long Rss,long long Rtt,int pred_in,int * pred_result)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
check_ll(long long val,long long expect)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
check(int val,int expect)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
check_p(int val,int expect)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
test_sfrecipa()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
test_sfinvsqrta()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
test_vacsh()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
test_vminub()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
test_add_carry()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
test_sub_carry()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
main()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