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