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
sfrecipa(int32_t Rs,int32_t Rt,bool * pred_result)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
sfinvsqrta(int32_t Rs,int32_t * pred_result)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
vacsh(int64_t Rxx,int64_t Rss,int64_t Rtt,int * pred_result,bool * ovf_result)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
vminub(int64_t Rtt,int64_t Rss,int32_t * pred_result)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
add_carry(int64_t Rss,int64_t Rtt,int32_t pred_in,int32_t * pred_result)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
sub_carry(int64_t Rss,int64_t Rtt,int32_t pred_in,int32_t * pred_result)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
test_sfrecipa()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
test_sfinvsqrta()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
test_vacsh()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
test_vminub()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
test_add_carry()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
test_sub_carry()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
main()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