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