xref: /openbmc/qemu/tests/tcg/hexagon/overflow.c (revision 9c9fff18c45b54fd9adf2282323aab1b6f0ec866)
1b9dd6ff9STaylor Simpson /*
2*0d57cd61STaylor Simpson  *  Copyright(c) 2021-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
3b9dd6ff9STaylor Simpson  *
4b9dd6ff9STaylor Simpson  *  This program is free software; you can redistribute it and/or modify
5b9dd6ff9STaylor Simpson  *  it under the terms of the GNU General Public License as published by
6b9dd6ff9STaylor Simpson  *  the Free Software Foundation; either version 2 of the License, or
7b9dd6ff9STaylor Simpson  *  (at your option) any later version.
8b9dd6ff9STaylor Simpson  *
9b9dd6ff9STaylor Simpson  *  This program is distributed in the hope that it will be useful,
10b9dd6ff9STaylor Simpson  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11b9dd6ff9STaylor Simpson  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12b9dd6ff9STaylor Simpson  *  GNU General Public License for more details.
13b9dd6ff9STaylor Simpson  *
14b9dd6ff9STaylor Simpson  *  You should have received a copy of the GNU General Public License
15b9dd6ff9STaylor Simpson  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16b9dd6ff9STaylor Simpson  */
17b9dd6ff9STaylor Simpson 
18b9dd6ff9STaylor Simpson #include <stdlib.h>
19b9dd6ff9STaylor Simpson #include <stdio.h>
20*0d57cd61STaylor Simpson #include <stdint.h>
21b9dd6ff9STaylor Simpson #include <unistd.h>
22b9dd6ff9STaylor Simpson #include <sys/types.h>
23b9dd6ff9STaylor Simpson #include <fcntl.h>
24b9dd6ff9STaylor Simpson #include <setjmp.h>
25b9dd6ff9STaylor Simpson #include <signal.h>
26b9dd6ff9STaylor Simpson 
27b9dd6ff9STaylor Simpson int err;
28b9dd6ff9STaylor Simpson 
29*0d57cd61STaylor Simpson #include "hex_test.h"
30b9dd6ff9STaylor Simpson 
satub(int32_t src,int32_t * p,bool * ovf_result)31*0d57cd61STaylor Simpson static int32_t satub(int32_t src, int32_t *p, bool *ovf_result)
32b9dd6ff9STaylor Simpson {
33*0d57cd61STaylor Simpson     int32_t result;
34*0d57cd61STaylor Simpson     uint32_t usr;
35b9dd6ff9STaylor Simpson 
36b9dd6ff9STaylor Simpson     /*
37b9dd6ff9STaylor Simpson      * This instruction can set bit 0 (OVF/overflow) in usr
38b9dd6ff9STaylor Simpson      * Clear the bit first, then return that bit to the caller
39b9dd6ff9STaylor Simpson      *
40b9dd6ff9STaylor Simpson      * We also store the src into *p in the same packet, so we
41b9dd6ff9STaylor Simpson      * can ensure the overflow doesn't get set when an exception
42b9dd6ff9STaylor Simpson      * is generated.
43b9dd6ff9STaylor Simpson      */
44b9dd6ff9STaylor Simpson     asm volatile("r2 = usr\n\t"
45b9dd6ff9STaylor Simpson                  "r2 = clrbit(r2, #0)\n\t"        /* clear overflow bit */
46b9dd6ff9STaylor Simpson                  "usr = r2\n\t"
47b9dd6ff9STaylor Simpson                  "{\n\t"
48b9dd6ff9STaylor Simpson                  "    %0 = satub(%2)\n\t"
49b9dd6ff9STaylor Simpson                  "    memw(%3) = %2\n\t"
50b9dd6ff9STaylor Simpson                  "}\n\t"
51b9dd6ff9STaylor Simpson                  "%1 = usr\n\t"
52b9dd6ff9STaylor Simpson                  : "=r"(result), "=r"(usr)
53b9dd6ff9STaylor Simpson                  : "r"(src), "r"(p)
54b9dd6ff9STaylor Simpson                  : "r2", "usr", "memory");
55b9dd6ff9STaylor Simpson   *ovf_result = (usr & 1);
56b9dd6ff9STaylor Simpson   return result;
57b9dd6ff9STaylor Simpson }
58b9dd6ff9STaylor Simpson 
read_usr_overflow(void)59*0d57cd61STaylor Simpson bool read_usr_overflow(void)
60b9dd6ff9STaylor Simpson {
61*0d57cd61STaylor Simpson     uint32_t usr;
62*0d57cd61STaylor Simpson     asm volatile("%0 = usr\n\t" : "=r"(usr));
63*0d57cd61STaylor Simpson     return usr & 1;
64b9dd6ff9STaylor Simpson }
65b9dd6ff9STaylor Simpson 
get_usr_overflow(uint32_t usr)66*0d57cd61STaylor Simpson bool get_usr_overflow(uint32_t usr)
678576e7ecSTaylor Simpson {
688576e7ecSTaylor Simpson     return usr & 1;
698576e7ecSTaylor Simpson }
708576e7ecSTaylor Simpson 
get_usr_fp_invalid(uint32_t usr)71*0d57cd61STaylor Simpson bool get_usr_fp_invalid(uint32_t usr)
728576e7ecSTaylor Simpson {
738576e7ecSTaylor Simpson     return (usr >> 1) & 1;
748576e7ecSTaylor Simpson }
758576e7ecSTaylor Simpson 
get_usr_lpcfg(uint32_t usr)76*0d57cd61STaylor Simpson int32_t get_usr_lpcfg(uint32_t usr)
778576e7ecSTaylor Simpson {
788576e7ecSTaylor Simpson     return (usr >> 8) & 0x3;
798576e7ecSTaylor Simpson }
80b9dd6ff9STaylor Simpson 
81b9dd6ff9STaylor Simpson jmp_buf jmp_env;
82*0d57cd61STaylor Simpson bool usr_overflow;
83b9dd6ff9STaylor Simpson 
sig_segv(int sig,siginfo_t * info,void * puc)84b9dd6ff9STaylor Simpson static void sig_segv(int sig, siginfo_t *info, void *puc)
85b9dd6ff9STaylor Simpson {
86b9dd6ff9STaylor Simpson     usr_overflow = read_usr_overflow();
87b9dd6ff9STaylor Simpson     longjmp(jmp_env, 1);
88b9dd6ff9STaylor Simpson }
89b9dd6ff9STaylor Simpson 
test_packet(void)908576e7ecSTaylor Simpson static void test_packet(void)
918576e7ecSTaylor Simpson {
92*0d57cd61STaylor Simpson     int32_t convres;
93*0d57cd61STaylor Simpson     int32_t satres;
94*0d57cd61STaylor Simpson     uint32_t usr;
958576e7ecSTaylor Simpson 
968576e7ecSTaylor Simpson     asm("r2 = usr\n\t"
978576e7ecSTaylor Simpson         "r2 = clrbit(r2, #0)\n\t"        /* clear overflow bit */
988576e7ecSTaylor Simpson         "r2 = clrbit(r2, #1)\n\t"        /* clear FP invalid bit */
998576e7ecSTaylor Simpson         "usr = r2\n\t"
1008576e7ecSTaylor Simpson         "{\n\t"
1018576e7ecSTaylor Simpson         "    %0 = convert_sf2uw(%3):chop\n\t"
1028576e7ecSTaylor Simpson         "    %1 = satb(%4)\n\t"
1038576e7ecSTaylor Simpson         "}\n\t"
1048576e7ecSTaylor Simpson         "%2 = usr\n\t"
1058576e7ecSTaylor Simpson         : "=r"(convres), "=r"(satres), "=r"(usr)
1068576e7ecSTaylor Simpson         : "r"(0x6a051b86), "r"(0x0410eec0)
1078576e7ecSTaylor Simpson         : "r2", "usr");
1088576e7ecSTaylor Simpson 
109*0d57cd61STaylor Simpson     check32(convres, 0xffffffff);
110*0d57cd61STaylor Simpson     check32(satres, 0x7f);
111*0d57cd61STaylor Simpson     check32(get_usr_overflow(usr), true);
112*0d57cd61STaylor Simpson     check32(get_usr_fp_invalid(usr), true);
1138576e7ecSTaylor Simpson 
1148576e7ecSTaylor Simpson     asm("r2 = usr\n\t"
1158576e7ecSTaylor Simpson         "r2 = clrbit(r2, #0)\n\t"        /* clear overflow bit */
1168576e7ecSTaylor Simpson         "usr = r2\n\t"
1178576e7ecSTaylor Simpson         "%2 = r2\n\t"
1188576e7ecSTaylor Simpson         "p3 = sp3loop0(1f, #1)\n\t"
1198576e7ecSTaylor Simpson         "1:\n\t"
1208576e7ecSTaylor Simpson         "{\n\t"
1218576e7ecSTaylor Simpson         "    %0 = satb(%2)\n\t"
1228576e7ecSTaylor Simpson         "}:endloop0\n\t"
1238576e7ecSTaylor Simpson         "%1 = usr\n\t"
1248576e7ecSTaylor Simpson         : "=r"(satres), "=r"(usr)
1258576e7ecSTaylor Simpson         : "r"(0x0410eec0)
1268576e7ecSTaylor Simpson         : "r2", "usr", "p3", "sa0", "lc0");
1278576e7ecSTaylor Simpson 
128*0d57cd61STaylor Simpson     check32(satres, 0x7f);
129*0d57cd61STaylor Simpson     check32(get_usr_overflow(usr), true);
130*0d57cd61STaylor Simpson     check32(get_usr_lpcfg(usr), 2);
1318576e7ecSTaylor Simpson }
1328576e7ecSTaylor Simpson 
main()133b9dd6ff9STaylor Simpson int main()
134b9dd6ff9STaylor Simpson {
135b9dd6ff9STaylor Simpson     struct sigaction act;
136*0d57cd61STaylor Simpson     bool ovf;
137b9dd6ff9STaylor Simpson 
138b9dd6ff9STaylor Simpson     /* SIGSEGV test */
139b9dd6ff9STaylor Simpson     act.sa_sigaction = sig_segv;
140b9dd6ff9STaylor Simpson     sigemptyset(&act.sa_mask);
141b9dd6ff9STaylor Simpson     act.sa_flags = SA_SIGINFO;
142b9dd6ff9STaylor Simpson     sigaction(SIGSEGV, &act, NULL);
143b9dd6ff9STaylor Simpson     if (setjmp(jmp_env) == 0) {
144b9dd6ff9STaylor Simpson         satub(300, 0, &ovf);
145b9dd6ff9STaylor Simpson     }
146b9dd6ff9STaylor Simpson 
147b9dd6ff9STaylor Simpson     act.sa_handler = SIG_DFL;
148b9dd6ff9STaylor Simpson     sigemptyset(&act.sa_mask);
149b9dd6ff9STaylor Simpson     act.sa_flags = 0;
150b9dd6ff9STaylor Simpson 
151*0d57cd61STaylor Simpson     check32(usr_overflow, false);
152b9dd6ff9STaylor Simpson 
1538576e7ecSTaylor Simpson     test_packet();
1548576e7ecSTaylor Simpson 
155b9dd6ff9STaylor Simpson     puts(err ? "FAIL" : "PASS");
156b9dd6ff9STaylor Simpson     return err ? EXIT_FAILURE : EXIT_SUCCESS;
157b9dd6ff9STaylor Simpson }
158