xref: /openbmc/qemu/target/riscv/m128_helper.c (revision 6edfca9e)
1 /*
2  * RISC-V Emulation Helpers for QEMU.
3  *
4  * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5  * Copyright (c) 2017-2018 SiFive, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2 or later, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "qemu/main-loop.h"
23 #include "exec/exec-all.h"
24 #include "exec/helper-proto.h"
25 
26 target_ulong HELPER(divu_i128)(CPURISCVState *env,
27                                target_ulong ul, target_ulong uh,
28                                target_ulong vl, target_ulong vh)
29 {
30     target_ulong ql, qh;
31     Int128 q;
32 
33     if (vl == 0 && vh == 0) { /* Handle special behavior on div by zero */
34         ql = ~0x0;
35         qh = ~0x0;
36     } else {
37         q = int128_divu(int128_make128(ul, uh), int128_make128(vl, vh));
38         ql = int128_getlo(q);
39         qh = int128_gethi(q);
40     }
41 
42     env->retxh = qh;
43     return ql;
44 }
45 
46 target_ulong HELPER(remu_i128)(CPURISCVState *env,
47                                target_ulong ul, target_ulong uh,
48                                target_ulong vl, target_ulong vh)
49 {
50     target_ulong rl, rh;
51     Int128 r;
52 
53     if (vl == 0 && vh == 0) {
54         rl = ul;
55         rh = uh;
56     } else {
57         r = int128_remu(int128_make128(ul, uh), int128_make128(vl, vh));
58         rl = int128_getlo(r);
59         rh = int128_gethi(r);
60     }
61 
62     env->retxh = rh;
63     return rl;
64 }
65 
66 target_ulong HELPER(divs_i128)(CPURISCVState *env,
67                                target_ulong ul, target_ulong uh,
68                                target_ulong vl, target_ulong vh)
69 {
70     target_ulong qh, ql;
71     Int128 q;
72 
73     if (vl == 0 && vh == 0) { /* Div by zero check */
74         ql = ~0x0;
75         qh = ~0x0;
76     } else if (uh == (1ULL << (TARGET_LONG_BITS - 1)) && ul == 0 &&
77                vh == ~0x0 && vl == ~0x0) {
78         /* Signed div overflow check (-2**127 / -1) */
79         ql = ul;
80         qh = uh;
81     } else {
82         q = int128_divs(int128_make128(ul, uh), int128_make128(vl, vh));
83         ql = int128_getlo(q);
84         qh = int128_gethi(q);
85     }
86 
87     env->retxh = qh;
88     return ql;
89 }
90 
91 target_ulong HELPER(rems_i128)(CPURISCVState *env,
92                                target_ulong ul, target_ulong uh,
93                                target_ulong vl, target_ulong vh)
94 {
95     target_ulong rh, rl;
96     Int128 r;
97 
98     if (vl == 0 && vh == 0) {
99         rl = ul;
100         rh = uh;
101     } else {
102         r = int128_rems(int128_make128(ul, uh), int128_make128(vl, vh));
103         rl = int128_getlo(r);
104         rh = int128_gethi(r);
105     }
106 
107     env->retxh = rh;
108     return rl;
109 }
110