diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-09 23:54:14 -0800 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-09 23:58:39 -0800 |
commit | ccf79891f0f1fcb570f9a63c15270b52477fe7c0 (patch) | |
tree | e86a1ef10afca65db9908df90616f58fd8fdbeb5 /machine/muldiv_emulation.c | |
parent | b94c7a4b07f96f24ae7411780abf874416549f7b (diff) | |
download | riscv-pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.zip riscv-pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.tar.gz riscv-pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.tar.bz2 |
Factor emulation routines into multiple files
Diffstat (limited to 'machine/muldiv_emulation.c')
-rw-r--r-- | machine/muldiv_emulation.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/machine/muldiv_emulation.c b/machine/muldiv_emulation.c new file mode 100644 index 0000000..d0583c5 --- /dev/null +++ b/machine/muldiv_emulation.c @@ -0,0 +1,64 @@ +#include "emulation.h" + +#ifndef __riscv_muldiv + +#ifdef __riscv64 +typedef __int128 double_int; +#else +typedef int64_t double_int; +#endif + +// These routines rely on the compiler to turn these operations into libcalls +// when not natively supported. So work on making those go fast. + +DECLARE_EMULATION_FUNC(emulate_mul_div) +{ + uintptr_t rs1 = GET_RS1(insn, regs), rs2 = GET_RS2(insn, regs), val; + + if ((insn & MASK_MUL) == MATCH_MUL) + val = rs1 * rs2; + else if ((insn & MASK_DIV) == MATCH_DIV) + val = (intptr_t)rs1 / (intptr_t)rs2; + else if ((insn & MASK_DIVU) == MATCH_DIVU) + val = rs1 / rs2; + else if ((insn & MASK_REM) == MATCH_REM) + val = (intptr_t)rs1 % (intptr_t)rs2; + else if ((insn & MASK_REMU) == MATCH_REMU) + val = rs1 % rs2; + else if ((insn & MASK_MULH) == MATCH_MULH) + val = ((double_int)(intptr_t)rs1 * (double_int)(intptr_t)rs2) >> (8 * sizeof(rs1)); + else if ((insn & MASK_MULHU) == MATCH_MULHU) + val = ((double_int)rs1 * (double_int)rs2) >> (8 * sizeof(rs1)); + else if ((insn & MASK_MULHSU) == MATCH_MULHSU) + val = ((double_int)(intptr_t)rs1 * (double_int)rs2) >> (8 * sizeof(rs1)); + else + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + + SET_RD(insn, regs, val); +} + +#ifdef __riscv64 + +DECLARE_EMULATION_FUNC(emulate_mul_div32) +{ + uint32_t rs1 = GET_RS1(insn, regs), rs2 = GET_RS2(insn, regs); + int32_t val; + + if ((insn & MASK_MULW) == MATCH_MULW) + val = rs1 * rs2; + else if ((insn & MASK_DIVW) == MATCH_DIVW) + val = (int32_t)rs1 / (int32_t)rs2; + else if ((insn & MASK_DIVUW) == MATCH_DIVUW) + val = rs1 / rs2; + else if ((insn & MASK_REMW) == MATCH_REMW) + val = (int32_t)rs1 % (int32_t)rs2; + else if ((insn & MASK_REMUW) == MATCH_REMUW) + val = rs1 % rs2; + else + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + + SET_RD(insn, regs, val); +} + +#endif +#endif |