qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

overflow.c (4109B)


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