aboutsummaryrefslogtreecommitdiff
path: root/machine/fp_ldst.c
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2016-03-09 23:54:14 -0800
committerAndrew Waterman <waterman@cs.berkeley.edu>2016-03-09 23:58:39 -0800
commitccf79891f0f1fcb570f9a63c15270b52477fe7c0 (patch)
treee86a1ef10afca65db9908df90616f58fd8fdbeb5 /machine/fp_ldst.c
parentb94c7a4b07f96f24ae7411780abf874416549f7b (diff)
downloadpk-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.c67
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);
+ }
+}
+