blob: 7bf115b85ef267f28ed60ed91f7db8b6b6b5208e [file] [log] [blame]
Frédéric Pétrotb3a5d1f2022-01-06 22:01:04 +01001/*
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
26target_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
46target_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
66target_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
91target_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}