4 #include <arch/softfloat.h>
6 static uint32_t ls(uint64_t* addr)
9 asm ("fld f0, %1; mftx.s %0, f0" : "=r"(r) : "m"(*addr));
13 static void ss(uint64_t* addr, uint32_t val)
15 asm ("mxtf.s f0, %0; fsd f0, %1" : : "r"(val), "m"(*addr));
18 static int emulate_fpu_silly(struct hw_trapframe *state,
19 ancillary_state_t *silly)
22 if (memcpy_from_user(current, &insn, (void*)state->epc, 4))
24 state->cause = CAUSE_FAULT_FETCH;
28 #define DECLARE_INSN(name, match, mask) bool is_##name = (insn & mask) == match;
29 #include <arch/opcodes.h>
32 int rd = (insn >> 27) & 0x1f;
33 int rs1 = (insn >> 22) & 0x1f;
34 int rs2 = (insn >> 17) & 0x1f;
35 int rs3 = (insn >> 12) & 0x1f;
37 int imm = (insn << 10) >> 20;
38 int bimm = ((insn >> 10) & 0x7f) | ((insn & 0xf8000000) >> 20);
40 void* load_address = (void*)(state->gpr[rs1] + imm);
41 void* store_address = (void*)(state->gpr[rs1] + bimm);
44 sf.float_rounding_mode = silly->fsr >> 5;
45 sf.float_exception_flags = silly->fsr & 0x1f;
48 ss(&silly->fpr[rd], float32_sqrt(&sf, ls(&silly->fpr[rs1])));
50 silly->fpr[rd] = float64_sqrt(&sf, silly->fpr[rs1]);
52 ss(&silly->fpr[rd], float32_div(&sf, ls(&silly->fpr[rs1]), ls(&silly->fpr[rs2])));
54 silly->fpr[rd] = float64_div(&sf, silly->fpr[rs1], silly->fpr[rs2]);
55 /* Eventually, we will emulate the full FPU, including the below insns
58 // use sf instead of silly->fsr
59 state->gpr[rd] = silly->fsr;
63 // use sf instead of silly->fsr
64 int temp = silly->fsr;
65 silly->fsr = state->gpr[rs1] & 0xFF;
66 state->gpr[rd] = silly->fsr;
71 if (!memcpy_from_user(current, &dest, load_address, sizeof(dest)))
73 state->cause = CAUSE_FAULT_LOAD;
74 state->badvaddr = (long)load_address;
77 silly->fpr[rd] = dest;
82 if (!memcpy_from_user(current, &dest, load_address, sizeof(dest)))
84 state->cause = CAUSE_FAULT_LOAD;
85 state->badvaddr = (long)load_address;
88 silly->fpr[rd] = dest;
92 if (!memcpy_to_user(current, store_address, &silly->fpr[rs2], sizeof(uint64_t)))
94 state->cause = CAUSE_FAULT_STORE;
95 state->badvaddr = (long)store_address;
101 if (!memcpy_to_user(current, store_address, &silly->fpr[rs2], sizeof(uint32_t)))
103 state->cause = CAUSE_FAULT_STORE;
104 state->badvaddr = (long)store_address;
112 silly->fsr = sf.float_rounding_mode << 5 | sf.float_exception_flags;
116 /* For now we can only emulate missing compute insns, not the whole FPU */
117 int emulate_fpu(struct hw_trapframe *state)
119 if (!(state->sr & SR_EF))
121 state->cause = CAUSE_FP_DISABLED;
125 ancillary_state_t fp_state;
126 save_fp_state(&fp_state);
127 int code = emulate_fpu_silly(state, &fp_state);
128 restore_fp_state(&fp_state);