1// See LICENSE for license details.
2
3#include "emulation.h"
4
5#ifndef __riscv_muldiv
6
7#if __riscv_xlen == 64
8typedef __int128 double_int;
9#else
10typedef int64_t double_int;
11#endif
12
13// These routines rely on the compiler to turn these operations into libcalls
14// when not natively supported.  So work on making those go fast.
15
16DECLARE_EMULATION_FUNC(emulate_mul_div)
17{
18  uintptr_t rs1 = GET_RS1(insn, regs), rs2 = GET_RS2(insn, regs), val;
19
20  if ((insn & MASK_MUL) == MATCH_MUL)
21    val = rs1 * rs2;
22  else if ((insn & MASK_DIV) == MATCH_DIV)
23    val = (intptr_t)rs1 / (intptr_t)rs2;
24  else if ((insn & MASK_DIVU) == MATCH_DIVU)
25    val = rs1 / rs2;
26  else if ((insn & MASK_REM) == MATCH_REM)
27    val = (intptr_t)rs1 % (intptr_t)rs2;
28  else if ((insn & MASK_REMU) == MATCH_REMU)
29    val = rs1 % rs2;
30  else if ((insn & MASK_MULH) == MATCH_MULH)
31    val = ((double_int)(intptr_t)rs1 * (double_int)(intptr_t)rs2) >> (8 * sizeof(rs1));
32  else if ((insn & MASK_MULHU) == MATCH_MULHU)
33    val = ((double_int)rs1 * (double_int)rs2) >> (8 * sizeof(rs1));
34  else if ((insn & MASK_MULHSU) == MATCH_MULHSU)
35    val = ((double_int)(intptr_t)rs1 * (double_int)rs2) >> (8 * sizeof(rs1));
36  else
37    return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
38
39  SET_RD(insn, regs, val);
40}
41
42#if __riscv_xlen == 64
43
44DECLARE_EMULATION_FUNC(emulate_mul_div32)
45{
46  uint32_t rs1 = GET_RS1(insn, regs), rs2 = GET_RS2(insn, regs);
47  int32_t val;
48
49  if ((insn & MASK_MULW) == MATCH_MULW)
50    val = rs1 * rs2;
51  else if ((insn & MASK_DIVW) == MATCH_DIVW)
52    val = (int32_t)rs1 / (int32_t)rs2;
53  else if ((insn & MASK_DIVUW) == MATCH_DIVUW)
54    val = rs1 / rs2;
55  else if ((insn & MASK_REMW) == MATCH_REMW)
56    val = (int32_t)rs1 % (int32_t)rs2;
57  else if ((insn & MASK_REMUW) == MATCH_REMUW)
58    val = rs1 % rs2;
59  else
60    return truly_illegal_insn(regs, mcause, mepc, mstatus, insn);
61
62  SET_RD(insn, regs, val);
63}
64
65#endif
66#endif
67