1 INTERFACE [arm && fpu]:
6 struct Exception_state_user
13 Mword fpsid() const { return _fpsid; }
24 Mword state[32 * 4]; // 4*32 bytes for each FP-reg
27 static Mword fpsid_rev(Mword v) { return v & 0xf; }
28 static Mword fpsid_variant(Mword v) { return (v >> 4) & 0xf; }
29 static Mword fpsid_part_number(Mword v) { return (v >> 8) & 0xff; }
30 static Mword fpsid_arch_version(Mword v) { return (v >> 16) & 0xf; }
31 static Mword fpsid_precision(Mword v) { return (v >> 20) & 1; }
32 static Mword fpsid_format(Mword v) { return (v >> 21) & 3; }
33 static Mword fpsid_hw_sw(Mword v) { return (v >> 23) & 1; }
34 static Mword fpsid_implementer(Mword v) { return v >> 24; }
40 // ------------------------------------------------------------------------
41 INTERFACE [arm && !fpu]:
46 struct Exception_state_user
51 // ------------------------------------------------------------------------
52 IMPLEMENTATION [arm && !fpu]:
54 #include "trap_state.h"
56 PUBLIC static inline NEEDS["trap_state.h"]
58 Fpu::save_user_exception_state(Trap_state *, Exception_state_user *)
61 // ------------------------------------------------------------------------
62 IMPLEMENTATION [arm && fpu]:
68 #include "fpu_state.h"
70 #include "processor.h"
71 #include "static_assert.h"
72 #include "trap_state.h"
79 asm volatile("mrc p10, 7, %0, cr0, cr0" : "=r" (v));
88 asm volatile("mrc p10, 7, %0, cr7, cr0" : "=r" (v));
97 asm volatile("mrc p10, 7, %0, cr6, cr0" : "=r" (v));
102 PRIVATE static inline
106 asm volatile("mcr p10, 7, %0, cr8, cr0" : : "r" (v));
114 asm volatile("mrc p10, 7, %0, cr8, cr0" : "=r" (v));
123 asm volatile("mcr p10, 7, %0, cr9, cr0" : "=r" (i));
132 asm volatile("mcr p10, 7, %0, cr10, cr0" : "=r" (i));
140 return fpexc() & FPEXC_EX;
147 fpexc((fpexc() | FPEXC_EN) & ~FPEXC_EX);
154 fpexc(fpexc() & ~FPEXC_EN);
159 Fpu::emulate_insns(Mword opcode, Trap_state *ts, unsigned cpu)
161 unsigned reg = (opcode >> 16) & 0xf;
162 unsigned rt = (opcode >> 12) & 0xf;
163 Mword fpsid = Fpu::fpu(cpu).fpsid();
170 if (Fpu::fpsid_arch_version(fpsid) < 2)
172 ts->r[rt] = Fpu::mvfr1();
175 if (Fpu::fpsid_arch_version(fpsid) < 2)
177 ts->r[rt] = Fpu::mvfr0();
183 if (ts->psr & Proc::Status_thumb)
193 Fpu::init(unsigned cpu)
195 asm volatile(" mcr p15, 0, %0, c1, c0, 2 \n" : : "r"(0x00f00000));
198 Mword s = fpsid_read();
200 _fpu.cpu(cpu)._fpsid = s;
202 printf("FPU%d: Arch: %s(%lx), Part: %s(%lx), r: %lx, v: %lx, i: %lx, t: %s, p: %s\n",
203 cpu, fpsid_arch_version(s) == 1
205 : (fpsid_arch_version(s) == 3 ? "VFPv3" : "Unkn"),
206 fpsid_arch_version(s),
207 fpsid_part_number(s) == 0x20
209 : (fpsid_part_number(s) == 0x30 ? "VFPv3" : "Unkn"),
210 fpsid_part_number(s),
211 fpsid_rev(s), fpsid_variant(s), fpsid_implementer(s),
212 fpsid_hw_sw(s) ? "soft" : "hard",
213 fpsid_precision(s) ? "sngl" : "dbl/sngl");
220 IMPLEMENT inline NEEDS ["fpu_state.h", "mem.h", "static_assert.h", <cstring>]
222 Fpu::init_state (Fpu_state *s)
224 Fpu_regs *fpu_regs = reinterpret_cast<Fpu_regs *>(s->state_buffer());
225 static_assert(!(sizeof (*fpu_regs) % sizeof(Mword)),
226 "Non-mword size of Fpu_regs");
227 Mem::memset_mwords(fpu_regs, 0, sizeof (*fpu_regs) / sizeof(Mword));
232 Fpu::save_state(Fpu_state *s)
234 assert(s->state_buffer());
235 Fpu_regs *fpu_regs = reinterpret_cast<Fpu_regs *>(s->state_buffer());
237 asm volatile ("stc p11, cr0, [%0], #32*4 \n"
238 : : "r" (fpu_regs->state));
239 asm volatile ("mrc p10, 7, %0, cr8, cr0, 0 \n"
240 "mrc p10, 7, %1, cr1, cr0, 0 \n"
241 : "=r" (fpu_regs->fpexc),
242 "=r" (fpu_regs->fpscr));
247 Fpu::restore_state (Fpu_state *s)
249 assert (s->state_buffer());
250 Fpu_regs *fpu_regs = reinterpret_cast<Fpu_regs *>(s->state_buffer());
252 asm volatile ("ldc p11, cr0, [%0], #32*4 \n"
253 : : "r" (fpu_regs->state));
254 asm volatile ("mcr p10, 7, %0, cr8, cr0, 0 \n"
255 "mcr p10, 7, %1, cr1, cr0, 0 \n"
257 : "r" (fpu_regs->fpexc | FPEXC_EN),
258 "r" (fpu_regs->fpscr));
261 asm volatile("mcr p10, 7, %2, cr9, cr0, 0 \n"
262 "mcr p10, 7, %3, cr10, cr0, 0 \n"
264 : "r" (fpu_regs->fpinst),
265 "r" (fpu_regs->fpinst2));
272 { return sizeof (Fpu_regs); }
283 return fpexc() & FPEXC_EN;
286 PUBLIC static inline NEEDS["trap_state.h"]
288 Fpu::save_user_exception_state(Trap_state *ts, Exception_state_user *esu)
290 if ((ts->error_code & 0x01f00000) == 0x01100000)
292 esu->fpexc = Fpu::fpexc();
293 if (ts->error_code == 0x03100000)
295 esu->fpinst = Fpu::fpinst();
296 esu->fpinst2 = Fpu::fpinst2();