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/fp_ldst.c | |
parent | b94c7a4b07f96f24ae7411780abf874416549f7b (diff) | |
download | pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.zip pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.tar.gz pk-ccf79891f0f1fcb570f9a63c15270b52477fe7c0.tar.bz2 |
Factor emulation routines into multiple files
Diffstat (limited to 'machine/fp_ldst.c')
-rw-r--r-- | machine/fp_ldst.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/machine/fp_ldst.c b/machine/fp_ldst.c new file mode 100644 index 0000000..9d0a49f --- /dev/null +++ b/machine/fp_ldst.c @@ -0,0 +1,67 @@ +#include "fp_emulation.h" +#include "unprivileged_memory.h" + +DECLARE_EMULATION_FUNC(emulate_float_load) +{ + uint64_t val; + uintptr_t addr = GET_RS1(insn, regs) + IMM_I(insn); + + switch (insn & MASK_FUNCT3) + { + case MATCH_FLW & MASK_FUNCT3: + if (addr % 4 != 0) + return misaligned_load_trap(regs, mcause, mepc); + + SET_F32_RD(insn, regs, load_int32_t((void *)addr, mepc)); + break; + + case MATCH_FLD & MASK_FUNCT3: + if (addr % sizeof(uintptr_t) != 0) + return misaligned_load_trap(regs, mcause, mepc); + +#ifdef __riscv64 + val = load_uint64_t((void *)addr, mepc); +#else + val = load_uint32_t(addr, mepc); + val += (uint64_t)load_uint32_t((void *)(addr + 4), mepc) << 32; +#endif + SET_F64_RD(insn, regs, val); + break; + + default: + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + } +} + +DECLARE_EMULATION_FUNC(emulate_float_store) +{ + uint64_t val; + uintptr_t addr = GET_RS1(insn, regs) + IMM_S(insn); + + switch (insn & MASK_FUNCT3) + { + case MATCH_FSW & MASK_FUNCT3: + if (addr % 4 != 0) + return misaligned_store_trap(regs, mcause, mepc); + + store_uint32_t((void *)addr, GET_F32_RS2(insn, regs), mepc); + break; + + case MATCH_FSD & MASK_FUNCT3: + if (addr % sizeof(uintptr_t) != 0) + return misaligned_store_trap(regs, mcause, mepc); + + val = GET_F64_RS2(insn, regs); +#ifdef __riscv64 + store_uint64_t((void *)addr, val, mepc); +#else + store_uint32_t((void *)addr, val, mepc); + store_uint32_t((void *)(addr + 4), val >> 32, mepc); +#endif + break; + + default: + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + } +} + |