1 /* 2 * Copyright(c) 2021-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 <stdlib.h> 19 #include <stdio.h> 20 #include <stdint.h> 21 #include <unistd.h> 22 #include <sys/types.h> 23 #include <fcntl.h> 24 #include <setjmp.h> 25 #include <signal.h> 26 27 int err; 28 29 #include "hex_test.h" 30 31 static int32_t satub(int32_t src, int32_t *p, bool *ovf_result) 32 { 33 int32_t result; 34 uint32_t usr; 35 36 /* 37 * This instruction can set bit 0 (OVF/overflow) in usr 38 * Clear the bit first, then return that bit to the caller 39 * 40 * We also store the src into *p in the same packet, so we 41 * can ensure the overflow doesn't get set when an exception 42 * is generated. 43 */ 44 asm volatile("r2 = usr\n\t" 45 "r2 = clrbit(r2, #0)\n\t" /* clear overflow bit */ 46 "usr = r2\n\t" 47 "{\n\t" 48 " %0 = satub(%2)\n\t" 49 " memw(%3) = %2\n\t" 50 "}\n\t" 51 "%1 = usr\n\t" 52 : "=r"(result), "=r"(usr) 53 : "r"(src), "r"(p) 54 : "r2", "usr", "memory"); 55 *ovf_result = (usr & 1); 56 return result; 57 } 58 59 bool read_usr_overflow(void) 60 { 61 uint32_t usr; 62 asm volatile("%0 = usr\n\t" : "=r"(usr)); 63 return usr & 1; 64 } 65 66 bool get_usr_overflow(uint32_t usr) 67 { 68 return usr & 1; 69 } 70 71 bool get_usr_fp_invalid(uint32_t usr) 72 { 73 return (usr >> 1) & 1; 74 } 75 76 int32_t get_usr_lpcfg(uint32_t usr) 77 { 78 return (usr >> 8) & 0x3; 79 } 80 81 jmp_buf jmp_env; 82 bool usr_overflow; 83 84 static void sig_segv(int sig, siginfo_t *info, void *puc) 85 { 86 usr_overflow = read_usr_overflow(); 87 longjmp(jmp_env, 1); 88 } 89 90 static void test_packet(void) 91 { 92 int32_t convres; 93 int32_t satres; 94 uint32_t usr; 95 96 asm("r2 = usr\n\t" 97 "r2 = clrbit(r2, #0)\n\t" /* clear overflow bit */ 98 "r2 = clrbit(r2, #1)\n\t" /* clear FP invalid bit */ 99 "usr = r2\n\t" 100 "{\n\t" 101 " %0 = convert_sf2uw(%3):chop\n\t" 102 " %1 = satb(%4)\n\t" 103 "}\n\t" 104 "%2 = usr\n\t" 105 : "=r"(convres), "=r"(satres), "=r"(usr) 106 : "r"(0x6a051b86), "r"(0x0410eec0) 107 : "r2", "usr"); 108 109 check32(convres, 0xffffffff); 110 check32(satres, 0x7f); 111 check32(get_usr_overflow(usr), true); 112 check32(get_usr_fp_invalid(usr), true); 113 114 asm("r2 = usr\n\t" 115 "r2 = clrbit(r2, #0)\n\t" /* clear overflow bit */ 116 "usr = r2\n\t" 117 "%2 = r2\n\t" 118 "p3 = sp3loop0(1f, #1)\n\t" 119 "1:\n\t" 120 "{\n\t" 121 " %0 = satb(%2)\n\t" 122 "}:endloop0\n\t" 123 "%1 = usr\n\t" 124 : "=r"(satres), "=r"(usr) 125 : "r"(0x0410eec0) 126 : "r2", "usr", "p3", "sa0", "lc0"); 127 128 check32(satres, 0x7f); 129 check32(get_usr_overflow(usr), true); 130 check32(get_usr_lpcfg(usr), 2); 131 } 132 133 int main() 134 { 135 struct sigaction act; 136 bool ovf; 137 138 /* SIGSEGV test */ 139 act.sa_sigaction = sig_segv; 140 sigemptyset(&act.sa_mask); 141 act.sa_flags = SA_SIGINFO; 142 sigaction(SIGSEGV, &act, NULL); 143 if (setjmp(jmp_env) == 0) { 144 satub(300, 0, &ovf); 145 } 146 147 act.sa_handler = SIG_DFL; 148 sigemptyset(&act.sa_mask); 149 act.sa_flags = 0; 150 151 check32(usr_overflow, false); 152 153 test_packet(); 154 155 puts(err ? "FAIL" : "PASS"); 156 return err ? EXIT_FAILURE : EXIT_SUCCESS; 157 } 158