diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-07-16 16:16:22 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-07-16 16:16:22 -0700 |
commit | 023ae43e8d7b1cdd54ebdc98beeb6dae9dd6f05a (patch) | |
tree | 54d6ce5311ff94c2df38b339b11ca2fc98b319f1 /machine | |
parent | 6bead31951a5f70508b343681a6f6905324f7bec (diff) | |
download | riscv-pk-023ae43e8d7b1cdd54ebdc98beeb6dae9dd6f05a.zip riscv-pk-023ae43e8d7b1cdd54ebdc98beeb6dae9dd6f05a.tar.gz riscv-pk-023ae43e8d7b1cdd54ebdc98beeb6dae9dd6f05a.tar.bz2 |
Add FCLASS emulation
Diffstat (limited to 'machine')
-rw-r--r-- | machine/emulation.h | 4 | ||||
-rw-r--r-- | machine/fp_emulation.c | 24 |
2 files changed, 21 insertions, 7 deletions
diff --git a/machine/emulation.h b/machine/emulation.h index f1a71ec..b8712b5 100644 --- a/machine/emulation.h +++ b/machine/emulation.h @@ -11,8 +11,8 @@ typedef void (*emulation_func)(uintptr_t*, uintptr_t, uintptr_t, uintptr_t, insn void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc); void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc); -void redirect_trap(uintptr_t epc, uintptr_t mstatus); -DECLARE_EMULATION_FUNC(truly_illegal_insn); +void redirect_trap(uintptr_t epc, uintptr_t mstatus) __attribute__((noreturn)); +DECLARE_EMULATION_FUNC(truly_illegal_insn) __attribute__((noreturn)); #define GET_REG(insn, pos, regs) ({ \ int mask = (1 << (5+LOG_REGBYTES)) - (1 << LOG_REGBYTES); \ diff --git a/machine/fp_emulation.c b/machine/fp_emulation.c index f1ed919..be9c067 100644 --- a/machine/fp_emulation.c +++ b/machine/fp_emulation.c @@ -337,14 +337,26 @@ success: DECLARE_EMULATION_FUNC(emulate_fmv_if) { uintptr_t result; - if ((insn & MASK_FMV_X_S) == MATCH_FMV_X_S) + if ((insn >> 20) & 0x1f) + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + + if (GET_PRECISION(insn) == PRECISION_S) { result = GET_F32_RS1(insn, regs); -#ifdef __riscv64 - else if ((insn & MASK_FMV_X_D) == MATCH_FMV_X_D) + switch (GET_RM(insn)) { + case GET_RM(MATCH_FMV_X_S): break; + case GET_RM(MATCH_FCLASS_S): result = f32_classify(result); break; + default: return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + } + } else if (GET_PRECISION(insn) == PRECISION_D) { result = GET_F64_RS1(insn, regs); -#endif - else + switch (GET_RM(insn)) { + case GET_RM(MATCH_FMV_X_D): break; + case GET_RM(MATCH_FCLASS_D): result = f64_classify(result); break; + default: return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + } + } else { return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + } SET_RD(insn, regs, result); } @@ -355,8 +367,10 @@ DECLARE_EMULATION_FUNC(emulate_fmv_fi) if ((insn & MASK_FMV_S_X) == MATCH_FMV_S_X) SET_F32_RD(insn, regs, rs1); +#ifdef __riscv64 else if ((insn & MASK_FMV_D_X) == MATCH_FMV_D_X) SET_F64_RD(insn, regs, rs1); +#endif else return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); } |