/* * RISC-V Emulation Helpers for QEMU. * * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu * Copyright (c) 2017-2018 SiFive, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2 or later, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "qemu/osdep.h" #include "cpu.h" #include "qemu/main-loop.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" target_ulong HELPER(divu_i128)(CPURISCVState *env, target_ulong ul, target_ulong uh, target_ulong vl, target_ulong vh) { target_ulong ql, qh; Int128 q; if (vl == 0 && vh == 0) { /* Handle special behavior on div by zero */ ql = ~0x0; qh = ~0x0; } else { q = int128_divu(int128_make128(ul, uh), int128_make128(vl, vh)); ql = int128_getlo(q); qh = int128_gethi(q); } env->retxh = qh; return ql; } target_ulong HELPER(remu_i128)(CPURISCVState *env, target_ulong ul, target_ulong uh, target_ulong vl, target_ulong vh) { target_ulong rl, rh; Int128 r; if (vl == 0 && vh == 0) { rl = ul; rh = uh; } else { r = int128_remu(int128_make128(ul, uh), int128_make128(vl, vh)); rl = int128_getlo(r); rh = int128_gethi(r); } env->retxh = rh; return rl; } target_ulong HELPER(divs_i128)(CPURISCVState *env, target_ulong ul, target_ulong uh, target_ulong vl, target_ulong vh) { target_ulong qh, ql; Int128 q; if (vl == 0 && vh == 0) { /* Div by zero check */ ql = ~0x0; qh = ~0x0; } else if (uh == (1ULL << (TARGET_LONG_BITS - 1)) && ul == 0 && vh == ~0x0 && vl == ~0x0) { /* Signed div overflow check (-2**127 / -1) */ ql = ul; qh = uh; } else { q = int128_divs(int128_make128(ul, uh), int128_make128(vl, vh)); ql = int128_getlo(q); qh = int128_gethi(q); } env->retxh = qh; return ql; } target_ulong HELPER(rems_i128)(CPURISCVState *env, target_ulong ul, target_ulong uh, target_ulong vl, target_ulong vh) { target_ulong rh, rl; Int128 r; if (vl == 0 && vh == 0) { rl = ul; rh = uh; } else { r = int128_rems(int128_make128(ul, uh), int128_make128(vl, vh)); rl = int128_getlo(r); rh = int128_gethi(r); } env->retxh = rh; return rl; }