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 && !armv6plus]:
69 // ------------------------------------------------------------------------
70 IMPLEMENTATION [arm && fpu && armv6plus]:
76 asm volatile("mrc p15, 0, %0, c1, c0, 2\n"
78 "mcr p15, 0, %0, c1, c0, 2\n"
79 : : "r" (0), "I" (0x00f00000));
83 // ------------------------------------------------------------------------
84 IMPLEMENTATION [arm && fpu]:
90 #include "fpu_state.h"
92 #include "processor.h"
93 #include "static_assert.h"
94 #include "trap_state.h"
101 asm volatile("mrc p10, 7, %0, cr0, cr0" : "=r" (v));
110 asm volatile("mrc p10, 7, %0, cr7, cr0" : "=r" (v));
119 asm volatile("mrc p10, 7, %0, cr6, cr0" : "=r" (v));
124 PRIVATE static inline
128 asm volatile("mcr p10, 7, %0, cr8, cr0" : : "r" (v));
136 asm volatile("mrc p10, 7, %0, cr8, cr0" : "=r" (v));
145 asm volatile("mcr p10, 7, %0, cr9, cr0" : "=r" (i));
154 asm volatile("mcr p10, 7, %0, cr10, cr0" : "=r" (i));
162 return fpexc() & FPEXC_EX;
169 fpexc((fpexc() | FPEXC_EN) & ~FPEXC_EX);
176 fpexc(fpexc() & ~FPEXC_EN);
181 Fpu::is_emu_insn(Mword opcode)
183 return (opcode & 0x0ff00f90) == 0x0ef00a10;
188 Fpu::emulate_insns(Mword opcode, Trap_state *ts)
190 unsigned reg = (opcode >> 16) & 0xf;
191 unsigned rt = (opcode >> 12) & 0xf;
192 Mword fpsid = Fpu::fpu.current().fpsid();
199 if (Fpu::fpsid_arch_version(fpsid) < 2)
201 ts->r[rt] = Fpu::mvfr1();
204 if (Fpu::fpsid_arch_version(fpsid) < 2)
206 ts->r[rt] = Fpu::mvfr0();
212 if (ts->psr & Proc::Status_thumb)
222 Fpu::init(unsigned cpu)
226 Mword s = fpsid_read();
228 fpu.cpu(cpu)._fpsid = s;
230 printf("FPU%d: Arch: %s(%lx), Part: %s(%lx), r: %lx, v: %lx, i: %lx, t: %s, p: %s\n",
231 cpu, fpsid_arch_version(s) == 1
233 : (fpsid_arch_version(s) == 3 ? "VFPv3" : "Unkn"),
234 fpsid_arch_version(s),
235 fpsid_part_number(s) == 0x20
237 : (fpsid_part_number(s) == 0x30 ? "VFPv3" : "Unkn"),
238 fpsid_part_number(s),
239 fpsid_rev(s), fpsid_variant(s), fpsid_implementer(s),
240 fpsid_hw_sw(s) ? "soft" : "hard",
241 fpsid_precision(s) ? "sngl" : "dbl/sngl");
245 fpu.cpu(cpu).set_owner(0);
248 IMPLEMENT inline NEEDS ["fpu_state.h", "mem.h", "static_assert.h", <cstring>]
250 Fpu::init_state (Fpu_state *s)
252 Fpu_regs *fpu_regs = reinterpret_cast<Fpu_regs *>(s->state_buffer());
253 static_assert(!(sizeof (*fpu_regs) % sizeof(Mword)),
254 "Non-mword size of Fpu_regs");
255 Mem::memset_mwords(fpu_regs, 0, sizeof (*fpu_regs) / sizeof(Mword));
260 Fpu::save_state(Fpu_state *s)
262 assert(s->state_buffer());
263 Fpu_regs *fpu_regs = reinterpret_cast<Fpu_regs *>(s->state_buffer());
265 asm volatile ("stc p11, cr0, [%0], #32*4 \n"
266 : : "r" (fpu_regs->state));
267 asm volatile ("mrc p10, 7, %0, cr8, cr0, 0 \n"
268 "mrc p10, 7, %1, cr1, cr0, 0 \n"
269 : "=r" (fpu_regs->fpexc),
270 "=r" (fpu_regs->fpscr));
275 Fpu::restore_state(Fpu_state *s)
277 assert (s->state_buffer());
278 Fpu_regs *fpu_regs = reinterpret_cast<Fpu_regs *>(s->state_buffer());
280 asm volatile ("ldc p11, cr0, [%0], #32*4 \n"
281 : : "r" (fpu_regs->state));
282 asm volatile ("mcr p10, 7, %0, cr8, cr0, 0 \n"
283 "mcr p10, 7, %1, cr1, cr0, 0 \n"
285 : "r" (fpu_regs->fpexc | FPEXC_EN),
286 "r" (fpu_regs->fpscr));
289 asm volatile("mcr p10, 7, %2, cr9, cr0, 0 \n"
290 "mcr p10, 7, %3, cr10, cr0, 0 \n"
292 : "r" (fpu_regs->fpinst),
293 "r" (fpu_regs->fpinst2));
300 { return sizeof (Fpu_regs); }
311 return fpexc() & FPEXC_EN;
314 PUBLIC static inline NEEDS["trap_state.h"]
316 Fpu::save_user_exception_state(Trap_state *ts, Exception_state_user *esu)
318 if ((ts->error_code & 0x01f00000) == 0x01100000)
320 esu->fpexc = Fpu::fpexc();
321 if (ts->error_code == 0x03100000)
323 esu->fpinst = Fpu::fpinst();
324 esu->fpinst2 = Fpu::fpinst2();