Removes extraneous x86 net files
[akaros.git] / kern / arch / riscv / fpu.c
1 #include <arch/trap.h>
2 #include <smp.h>
3 #include <umem.h>
4 #include <arch/softfloat.h>
5
6 static uint32_t ls(uint64_t* addr)
7 {
8         uint32_t r;
9         asm ("fld f0, %1; mftx.s %0, f0" : "=r"(r) : "m"(*addr));
10         return r;
11 }
12
13 static void ss(uint64_t* addr, uint32_t val)
14 {
15         asm ("mxtf.s f0, %0; fsd f0, %1" : : "r"(val), "m"(*addr));
16 }
17
18 static int emulate_fpu_silly(struct trapframe* state, ancillary_state_t* silly)
19 {
20         int insn;
21         if (memcpy_from_user(current, &insn, (void*)state->epc, 4))
22         {
23                 state->cause = CAUSE_FAULT_FETCH;
24                 handle_trap(state);
25         }
26
27         #define DECLARE_INSN(name, match, mask) bool is_##name = (insn & mask) == match;
28         #include <arch/opcodes.h>
29         #undef DECLARE_INSN
30
31         int rd  = (insn >> 27) & 0x1f;
32         int rs1 = (insn >> 22) & 0x1f;
33         int rs2 = (insn >> 17) & 0x1f;
34         int rs3 = (insn >> 12) & 0x1f;
35
36         int imm = (insn << 10) >> 20;
37         int bimm = ((insn >> 10) & 0x7f) | ((insn & 0xf8000000) >> 20);
38
39         void* load_address = (void*)(state->gpr[rs1] + imm);
40         void* store_address = (void*)(state->gpr[rs1] + bimm);
41
42         softfloat_t sf;
43         sf.float_rounding_mode = silly->fsr >> 5;
44         sf.float_exception_flags = silly->fsr & 0x1f;
45
46         if (is_fsqrt_s)
47                 ss(&silly->fpr[rd], float32_sqrt(&sf, ls(&silly->fpr[rs1])));
48         else if (is_fsqrt_d)
49                 silly->fpr[rd] = float64_sqrt(&sf, silly->fpr[rs1]);
50         else if (is_fdiv_s)
51                 ss(&silly->fpr[rd], float32_div(&sf, ls(&silly->fpr[rs1]), ls(&silly->fpr[rs2])));
52         else if (is_fdiv_d)
53                 silly->fpr[rd] = float64_div(&sf, silly->fpr[rs1], silly->fpr[rs2]);
54         /* Eventually, we will emulate the full FPU, including the below insns
55         else if (is_mffsr)
56         {
57                 // use sf instead of silly->fsr
58                 state->gpr[rd] = silly->fsr;
59         }
60         else if (is_mtfsr)
61         {
62                 // use sf instead of silly->fsr
63                 int temp = silly->fsr;
64                 silly->fsr = state->gpr[rs1] & 0xFF;
65                 state->gpr[rd] = silly->fsr;
66         }
67         else if (is_fld)
68         {
69                 uint64_t dest;
70                 if (!memcpy_from_user(current, &dest, load_address, sizeof(dest)))
71                 {
72                         state->cause = CAUSE_FAULT_LOAD;
73                         state->badvaddr = (long)load_address;
74                         handle_trap(state);
75                 }
76                 silly->fpr[rd] = dest;
77         }
78         else if (is_flw)
79         {
80                 uint32_t dest;
81                 if (!memcpy_from_user(current, &dest, load_address, sizeof(dest)))
82                 {
83                         state->cause = CAUSE_FAULT_LOAD;
84                         state->badvaddr = (long)load_address;
85                         handle_trap(state);
86                 }
87                 silly->fpr[rd] = dest;
88         }
89         else if (is_fsd)
90         {
91                 if (!memcpy_to_user(current, store_address, &silly->fpr[rs2], sizeof(uint64_t)))
92                 {
93                         state->cause = CAUSE_FAULT_STORE;
94                         state->badvaddr = (long)store_address;
95                         handle_trap(state);
96                 }
97         }
98         else if (is_flw)
99         {
100                 if (!memcpy_to_user(current, store_address, &silly->fpr[rs2], sizeof(uint32_t)))
101                 {
102                         state->cause = CAUSE_FAULT_STORE;
103                         state->badvaddr = (long)store_address;
104                         handle_trap(state);
105                 }
106         }
107         */
108         else
109           return 1;
110         
111         silly->fsr = sf.float_rounding_mode << 5 | sf.float_exception_flags;
112         return 0;
113 }
114
115 /* For now we can only emulate missing compute insns, not the whole FPU */
116 int emulate_fpu(struct trapframe* state)
117 {
118         if (!(state->sr & SR_EF))
119         {
120                 state->cause = CAUSE_FP_DISABLED;
121                 handle_trap(state);
122         }
123
124         ancillary_state_t fp_state;
125         save_fp_state(&fp_state);
126         int code = emulate_fpu_silly(state, &fp_state);
127         restore_fp_state(&fp_state);
128         return code;
129 }