15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/asm_linkage.h>
29 #include <sys/trap.h>
30 #include <sys/machpcb.h>
31 #include <sys/machtrap.h>
32 #include <sys/machsig.h>
33 #include <sys/machthread.h>
34
35 #if !defined(lint) && !defined(__lint)
36 #include "assym.h"
37 #endif /* lint */
38
39 /*
40 * Floating point trap handling.
41 *
42 * The FPU is always in a V9 current configuration.
43 *
44 * When a user process is first started via exec,
45 * floating point operations will be disabled by default.
46 * Upon execution of the first floating point instruction,
47 * a fp_disabled trap will be generated; then a word in
48 * the uarea is written signifying use of the floating point
49 * registers so that subsequent context switches will save
50 * and restore the floating point them. The trapped instruction
51 * will be restarted and processing will continue as normal.
52 *
53 * When a operation occurs that the hardware cannot properly
54 * handle, an unfinshed fp_op exception will be generated.
55 * Software routines in the kernel will be executed to
56 * simulate proper handling of such conditions.
57 *
64 * moved to sun4u/ml/machfloat.s.
65 *
66 * NOTE: This code DOES NOT SUPPORT KERNEL (DEVICE DRIVER)
67 * USE OF THE FPU
68 *
69 * Instructions for running without the hardware fpu:
70 * 1. Setting fpu_exists to 0 now only works on a DEBUG kernel.
71 * 2. adb -w unix and set fpu_exists, use_hw_bcopy, use_hw_copyio, and
72 * use_hw_bzero to 0 and rename libc_psr.so.1 in
73 * /usr/platform/sun4u/lib so that it will not get used by
74 * the libc bcopy routines. Then reboot the system and you
75 * should see the bootup message "FPU not in use".
76 * 3. To run kaos, you must comment out the code which sets the
77 * version number of the fsr to 7, in fldst: stfsr/stxfsr
78 * (unless you are running against a comparison system that
79 * has the same fsr version number).
80 * 4. The stqf{a}/ldqf{a} instructions cause kaos errors, for reasons
81 * that appear to be a kaos bug, so don't use them!
82 */
83
84 #if defined(lint) || defined(__lint)
85
86 #ifdef FP_DISABLED
87 int fpu_exists = 0;
88 #else
89 int fpu_exists = 1;
90 #endif
91
92 #else /* lint */
93
94 .section ".data"
95 .align 8
96 fsrholder:
97 .word 0 ! dummy place to write fsr
98 .word 0
99
100 DGDEF(fpu_exists) ! always exists for V9
101 #ifdef FP_DISABLED
102 .word 0
103 #else
104 .word 1 ! sundiag (gack) uses this variable
105 #endif
106
107 DGDEF(fpu_version)
108 .word -1
109
110 #endif /* lint */
111
112 /*
113 * FPU probe - read the %fsr and get fpu_version.
114 * Called from autoconf. If a %fq is created for
115 * future cpu versions, a fq_exists variable
116 * could be created by this function.
117 */
118
119 #if defined(lint) || defined(__lint)
120
121 /*ARGSUSED*/
122 void
123 fpu_probe(void)
124 {}
125
126 #else /* lint */
127
128 ENTRY_NP(fpu_probe)
129 wr %g0, FPRS_FEF, %fprs ! enable fpu in fprs
130 rdpr %pstate, %g2 ! read pstate, save value in %g2
131 or %g2, PSTATE_PEF, %g1 ! new pstate with fpu enabled
132 wrpr %g1, %g0, %pstate ! write pstate
133
134 sethi %hi(fsrholder), %g2
135 stx %fsr, [%g2 + %lo(fsrholder)]
136 ldx [%g2 + %lo(fsrholder)], %g2 ! snarf the FSR
137 set FSR_VER, %g1
138 and %g2, %g1, %g2 ! get version
139 srl %g2, FSR_VER_SHIFT, %g2 ! and shift it down
140 sethi %hi(fpu_version), %g3 ! save the FPU version
141 st %g2, [%g3 + %lo(fpu_version)]
142
143 ba fp_kstat_init ! initialize the fpu_kstat
144 wr %g0, %g0, %fprs ! disable fpu and clear fprs
145 SET_SIZE(fpu_probe)
146
147 #endif /* lint */
148
149 /*
150 * fp_clearregs(fp)
151 * struct v9_fpu *fp;
152 *
153 * Initialization for the hardware fpu.
154 * Clear the fsr and initialize registers to NaN (-1)
155 * The caller (fp_disabled) is supposed to update the fprs
156 * so when the return to userland is made, the fpu is enabled.
157 */
158
159 #if defined(lint) || defined(__lint)
160
161 /*ARGSUSED*/
162 void
163 fp_clearregs(kfpu_t *fp)
164 {}
165
166 #else /* lint */
167
168 ENTRY_NP(fp_clearregs)
169 ldx [%o0 + FPU_FSR], %fsr ! load fsr
170
171 mov -1, %g2 ! -1 is NaN
172 stx %g2, [%o0] ! initialize %f0
173 ldd [%o0], %d0
174 ldd [%o0], %d2
175 ldd [%o0], %d4
176 ldd [%o0], %d6
177 ldd [%o0], %d8
178 ldd [%o0], %d10
179 ldd [%o0], %d12
180 ldd [%o0], %d14
181 ldd [%o0], %d16
182 ldd [%o0], %d18
183 ldd [%o0], %d20
184 ldd [%o0], %d22
185 ldd [%o0], %d24
186 ldd [%o0], %d26
187 ldd [%o0], %d28
188 ldd [%o0], %d30
189 ldd [%o0], %d32
190 ldd [%o0], %d34
191 ldd [%o0], %d36
192 ldd [%o0], %d38
193 ldd [%o0], %d40
194 ldd [%o0], %d42
195 ldd [%o0], %d44
196 ldd [%o0], %d46
197 ldd [%o0], %d48
198 ldd [%o0], %d50
199 ldd [%o0], %d52
200 ldd [%o0], %d54
201 ldd [%o0], %d56
202 ldd [%o0], %d58
203 ldd [%o0], %d60
204 retl
205 ldd [%o0], %d62
206 SET_SIZE(fp_clearregs)
207
208 #endif /* lint */
209
210 /*
211 * void _fp_read_pfreg(pf, n)
212 * uint32_t *pf; Old freg value.
213 * unsigned n; Want to read register n
214 *
215 * {
216 * *pf = %f[n];
217 * }
218 *
219 * void
220 * _fp_write_pfreg(pf, n)
221 * uint32_t *pf; New freg value.
222 * unsigned n; Want to write register n.
223 *
224 * {
225 * %f[n] = *pf;
226 * }
227 */
228
229 #if defined(lint) || defined(__lint)
230
231 /*ARGSUSED*/
232 void
233 _fp_read_pfreg(uint32_t *pf, u_int n)
234 {}
235
236 /*ARGSUSED*/
237 void
238 _fp_write_pfreg(uint32_t *pf, u_int n)
239 {}
240
241 #else /* lint */
242
243 ENTRY_NP(_fp_read_pfreg)
244 sll %o1, 3, %o1 ! Table entries are 8 bytes each.
245 set .stable, %g1 ! g1 gets base of table.
246 jmp %g1 + %o1 ! Jump into table
247 nop ! Can't follow CTI by CTI.
248
249 ENTRY_NP(_fp_write_pfreg)
250 sll %o1, 3, %o1 ! Table entries are 8 bytes each.
251 set .ltable, %g1 ! g1 gets base of table.
252 jmp %g1 + %o1 ! Jump into table
253 nop ! Can't follow CTI by CTI.
254
255 #define STOREFP(n) jmp %o7+8 ; st %f/**/n, [%o0]
256
257 .stable:
258 STOREFP(0)
259 STOREFP(1)
260 STOREFP(2)
261 STOREFP(3)
262 STOREFP(4)
309 LOADFP(15)
310 LOADFP(16)
311 LOADFP(17)
312 LOADFP(18)
313 LOADFP(19)
314 LOADFP(20)
315 LOADFP(21)
316 LOADFP(22)
317 LOADFP(23)
318 LOADFP(24)
319 LOADFP(25)
320 LOADFP(26)
321 LOADFP(27)
322 LOADFP(28)
323 LOADFP(29)
324 LOADFP(30)
325 LOADFP(31)
326 SET_SIZE(_fp_read_pfreg)
327 SET_SIZE(_fp_write_pfreg)
328
329 #endif /* lint */
330
331 /*
332 * void _fp_read_pdreg(
333 * uint64_t *pd, Old dreg value.
334 * u_int n) Want to read register n
335 *
336 * {
337 * *pd = %d[n];
338 * }
339 *
340 * void
341 * _fp_write_pdreg(
342 * uint64_t *pd, New dreg value.
343 * u_int n) Want to write register n.
344 *
345 * {
346 * %d[n] = *pd;
347 * }
348 */
349
350 #if defined(lint) || defined(__lint)
351
352 /*ARGSUSED*/
353 void
354 _fp_read_pdreg(uint64_t *pd, u_int n)
355 {}
356
357 /*ARGSUSED*/
358 void
359 _fp_write_pdreg(uint64_t *pd, u_int n)
360 {}
361
362 #else /* lint */
363
364 ENTRY_NP(_fp_read_pdreg)
365 sll %o1, 3, %o1 ! Table entries are 8 bytes each.
366 set .dstable, %g1 ! g1 gets base of table.
367 jmp %g1 + %o1 ! Jump into table
368 nop ! Can't follow CTI by CTI.
369
370 ENTRY_NP(_fp_write_pdreg)
371 sll %o1, 3, %o1 ! Table entries are 8 bytes each.
372 set .dltable, %g1 ! g1 gets base of table.
373 jmp %g1 + %o1 ! Jump into table
374 nop ! Can't follow CTI by CTI.
375
376 #define STOREDP(n) jmp %o7+8 ; std %d/**/n, [%o0]
377
378 .dstable:
379 STOREDP(0)
380 STOREDP(2)
381 STOREDP(4)
382 STOREDP(6)
383 STOREDP(8)
430 LOADDP(30)
431 LOADDP(32)
432 LOADDP(34)
433 LOADDP(36)
434 LOADDP(38)
435 LOADDP(40)
436 LOADDP(42)
437 LOADDP(44)
438 LOADDP(46)
439 LOADDP(48)
440 LOADDP(50)
441 LOADDP(52)
442 LOADDP(54)
443 LOADDP(56)
444 LOADDP(58)
445 LOADDP(60)
446 LOADDP(62)
447 SET_SIZE(_fp_read_pdreg)
448 SET_SIZE(_fp_write_pdreg)
449
450 #endif /* lint */
451
452 #if defined(lint) || defined(__lint)
453
454 /*ARGSUSED*/
455 void
456 _fp_write_pfsr(uint64_t *fsr)
457 {}
458
459 #else /* lint */
460
461 ENTRY_NP(_fp_write_pfsr)
462 retl
463 ldx [%o0], %fsr
464 SET_SIZE(_fp_write_pfsr)
465
466 #endif /* lint */
467
468 #if defined(lint) || defined(__lint)
469
470 /*ARGSUSED*/
471 void
472 _fp_read_pfsr(uint64_t *fsr)
473 {}
474
475 #else /* lint */
476
477 ENTRY_NP(_fp_read_pfsr)
478 retl
479 stx %fsr, [%o0]
480 SET_SIZE(_fp_read_pfsr)
481
482 #endif /* lint */
483
484 #if defined(lint) || defined(__lint)
485
486 /*ARGSUSED*/
487 void
488 _fp_write_fprs(u_int fprs_val)
489 {}
490
491 #else /* lint */
492
493 ENTRY_NP(_fp_write_fprs)
494 retl
495 wr %o0, %g0, %fprs ! write fprs
496 SET_SIZE(_fp_write_fprs)
497
498 #endif /* lint */
499
500 #if defined(lint) || defined(__lint)
501
502 unsigned
503 _fp_read_fprs(void)
504 {return 0;}
505
506 #else /* lint */
507
508 ENTRY_NP(_fp_read_fprs)
509 retl
510 rd %fprs, %o0 ! save fprs
511 SET_SIZE(_fp_read_fprs)
512
513 #endif /* lint */
514
515 #if defined(lint) || defined(__lint)
516
517 unsigned
518 _fp_subcc_ccr(void)
519 {return 0;}
520
521 #else /* lint */
522
523 ENTRY_NP(_fp_subcc_ccr)
524 subcc %o0, %o1, %g0
525 retl
526 rd %ccr, %o0 ! save ccr
527 SET_SIZE(_fp_subcc_ccr)
528
529 #endif /* lint */
530
531 /*
532 * Floating Point Exceptions handled according to type:
533 * 2) unfinished_fpop
534 * re-execute the faulty instruction(s) using
535 * software emulation (must do every instruction in FQ)
536 * 3) unimplemented_fpop
537 * an unimplemented instruction, if it is legal,
538 * will cause emulation of the instruction (and all
539 * other instuctions in the FQ)
540 * 4) sequence_error
541 * panic, this should not happen, and if it does it
542 * it is the result of a kernel bug
543 *
544 * This code assumes the trap preamble has set up the window environment
545 * for execution of kernel code.
546 * Note: this code could be changed to be part of the cpu-specific
547 * (ie, Spitfire-specific) module code before final release.
548 */
549
550 #if defined(lint)
551
552 /* ARGSUSED */
553 void
554 _fp_exception(struct regs *rp, uint64_t fsr)
555 {}
556
557 #else /* lint */
558
559 ENTRY_NP(_fp_exception)
560 mov %o7, %l0 ! saved return address
561 mov %o0, %l1 ! saved *rp
562 set FSR_FTT, %o4 ! put FSR_FTT in %o4
563 xor %o4, 0xffffffffffffffff, %o3 ! xor FSR_FTT to get
564 and %o1, %o3, %o2 ! an fsr with a zero'd ftt
565 ldn [THREAD_REG + T_LWP], %o3 ! get lwp
566 ldn [%o3 + LWP_FPU], %l3 ! get lwp_fpu
567 stx %o2, [%l3 + FPU_FSR] ! save floating point status
568 and %o1, %o4, %g2 ! get the ftt trap type
569 #ifdef DEBUG
570 brnz,a,pt %g2, fttok
571 nop
572 set .badfpfttmsg, %o0 ! panic message
573 call panic ! %o1 has the fsr w/ftt value
574 nop
575 fttok:
576 #endif /* DEBUG */
577 srl %g2, FSR_FTT_SHIFT, %o4 ! check ftt
578 cmp %o4, FTT_SEQ ! sanity check for bogus exceptions
598 ! point simulator. There is no floating point queue, so we fake one.
599 !
600 call fp_precise ! fp_precise(®s)
601 mov %l1, %o0 ! saved *rp
602
603 fp_ret:
604 rd %fprs, %g1 ! read fprs, save value in %g1
605 st %g1, [%l3 + FPU_FPRS] ! save fprs
606 jmp %l0 + 8 ! jump to saved return address
607 stx %fsr, [%l3 + FPU_FSR] ! save fsr
608 SET_SIZE(_fp_exception)
609
610 .badfpexcpmsg:
611 .asciz "unexpected floating point exception %x"
612
613 #ifdef DEBUG
614 .badfpfttmsg:
615 .asciz "No floating point ftt, fsr %llx"
616 #endif /* DEBUG */
617
618 #endif /* lint */
619
620 /*
621 * Floating Point Exceptions.
622 * handled according to type:
623 * 1) IEEE_exception
624 * re-execute the faulty instruction(s) using
625 * software emulation (must do every instruction in FQ)
626 *
627 * This code assumes the trap preamble has set up the window environment
628 * for execution of kernel code.
629 */
630
631 #if defined(lint)
632
633 /* ARGSUSED */
634 void
635 _fp_ieee_exception(struct regs *rp, uint64_t fsr)
636 {}
637
638 #else /* lint */
639
640 ENTRY_NP(_fp_ieee_exception)
641 mov %o7, %l0 ! saved return address
642 mov %o0, %l1 ! saved *rp
643 mov %o1, %l2 ! saved fsr
644 set FSR_FTT, %o4 ! put FSR_FTT in %o4
645 xor %o4, 0xffffffffffffffff, %o3 ! ! xor FSR_FTT to get
646 and %o1, %o3, %o2 ! an fsr with a zero'd ftt
647 ldn [THREAD_REG + T_LWP], %o3 ! get lwp
648 ldn [%o3 + LWP_FPU], %l3 ! get lwp_fpu
649 stx %o2, [%l3 + FPU_FSR] ! save floating point status
650 stub %g0, [%l3 + FPU_QCNT] ! clear fpu_qcnt
651 and %o1, %o4, %g2 ! mask out trap type
652 #ifdef DEBUG
653 brnz,a,pt %g2, fttgd
654 nop
655 set .badfpfttmsg, %o0 ! panic message
656 call panic ! %o1 has the fsr w/ftt value
657 nop
658 fttgd:
659 #endif /* DEBUG */
706 or %g0, FPE_FLTINV, %o3 ! fp invalid code
707
708 cexec_err:
709 set .badfpcexcmsg, %o0 ! panic message
710 call panic ! panic if no cexc bit set
711 mov %g1, %o1
712 fpok:
713 mov %l1, %o0 ! saved *rp
714 call fpu_trap ! fpu_trap(®s, addr, type, code)
715 ldn [%o0 + PC_OFF], %o1 ! address of trapping instruction
716
717 rd %fprs, %g1 ! read fprs, save value in %g1
718 st %g1, [%l3 + FPU_FPRS] ! save fprs
719 jmp %l0 + 8 ! jump to saved return address
720 stx %fsr, [%l3 + FPU_FSR] ! save fsr
721 SET_SIZE(_fp_ieee_exception)
722
723 .badfpcexcmsg:
724 .asciz "No floating point exception, fsr %llx"
725
726 #endif /* lint */
|
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/asm_linkage.h>
29 #include <sys/trap.h>
30 #include <sys/machpcb.h>
31 #include <sys/machtrap.h>
32 #include <sys/machsig.h>
33 #include <sys/machthread.h>
34
35 #include "assym.h"
36
37 /*
38 * Floating point trap handling.
39 *
40 * The FPU is always in a V9 current configuration.
41 *
42 * When a user process is first started via exec,
43 * floating point operations will be disabled by default.
44 * Upon execution of the first floating point instruction,
45 * a fp_disabled trap will be generated; then a word in
46 * the uarea is written signifying use of the floating point
47 * registers so that subsequent context switches will save
48 * and restore the floating point them. The trapped instruction
49 * will be restarted and processing will continue as normal.
50 *
51 * When a operation occurs that the hardware cannot properly
52 * handle, an unfinshed fp_op exception will be generated.
53 * Software routines in the kernel will be executed to
54 * simulate proper handling of such conditions.
55 *
62 * moved to sun4u/ml/machfloat.s.
63 *
64 * NOTE: This code DOES NOT SUPPORT KERNEL (DEVICE DRIVER)
65 * USE OF THE FPU
66 *
67 * Instructions for running without the hardware fpu:
68 * 1. Setting fpu_exists to 0 now only works on a DEBUG kernel.
69 * 2. adb -w unix and set fpu_exists, use_hw_bcopy, use_hw_copyio, and
70 * use_hw_bzero to 0 and rename libc_psr.so.1 in
71 * /usr/platform/sun4u/lib so that it will not get used by
72 * the libc bcopy routines. Then reboot the system and you
73 * should see the bootup message "FPU not in use".
74 * 3. To run kaos, you must comment out the code which sets the
75 * version number of the fsr to 7, in fldst: stfsr/stxfsr
76 * (unless you are running against a comparison system that
77 * has the same fsr version number).
78 * 4. The stqf{a}/ldqf{a} instructions cause kaos errors, for reasons
79 * that appear to be a kaos bug, so don't use them!
80 */
81
82 .section ".data"
83 .align 8
84 fsrholder:
85 .word 0 ! dummy place to write fsr
86 .word 0
87
88 DGDEF(fpu_exists) ! always exists for V9
89 #ifdef FP_DISABLED
90 .word 0
91 #else
92 .word 1 ! sundiag (gack) uses this variable
93 #endif
94
95 DGDEF(fpu_version)
96 .word -1
97
98 /*
99 * FPU probe - read the %fsr and get fpu_version.
100 * Called from autoconf. If a %fq is created for
101 * future cpu versions, a fq_exists variable
102 * could be created by this function.
103 */
104
105 ENTRY_NP(fpu_probe)
106 wr %g0, FPRS_FEF, %fprs ! enable fpu in fprs
107 rdpr %pstate, %g2 ! read pstate, save value in %g2
108 or %g2, PSTATE_PEF, %g1 ! new pstate with fpu enabled
109 wrpr %g1, %g0, %pstate ! write pstate
110
111 sethi %hi(fsrholder), %g2
112 stx %fsr, [%g2 + %lo(fsrholder)]
113 ldx [%g2 + %lo(fsrholder)], %g2 ! snarf the FSR
114 set FSR_VER, %g1
115 and %g2, %g1, %g2 ! get version
116 srl %g2, FSR_VER_SHIFT, %g2 ! and shift it down
117 sethi %hi(fpu_version), %g3 ! save the FPU version
118 st %g2, [%g3 + %lo(fpu_version)]
119
120 ba fp_kstat_init ! initialize the fpu_kstat
121 wr %g0, %g0, %fprs ! disable fpu and clear fprs
122 SET_SIZE(fpu_probe)
123
124 /*
125 * fp_clearregs(fp)
126 * struct v9_fpu *fp;
127 *
128 * Initialization for the hardware fpu.
129 * Clear the fsr and initialize registers to NaN (-1)
130 * The caller (fp_disabled) is supposed to update the fprs
131 * so when the return to userland is made, the fpu is enabled.
132 */
133
134 ENTRY_NP(fp_clearregs)
135 ldx [%o0 + FPU_FSR], %fsr ! load fsr
136
137 mov -1, %g2 ! -1 is NaN
138 stx %g2, [%o0] ! initialize %f0
139 ldd [%o0], %d0
140 ldd [%o0], %d2
141 ldd [%o0], %d4
142 ldd [%o0], %d6
143 ldd [%o0], %d8
144 ldd [%o0], %d10
145 ldd [%o0], %d12
146 ldd [%o0], %d14
147 ldd [%o0], %d16
148 ldd [%o0], %d18
149 ldd [%o0], %d20
150 ldd [%o0], %d22
151 ldd [%o0], %d24
152 ldd [%o0], %d26
153 ldd [%o0], %d28
154 ldd [%o0], %d30
155 ldd [%o0], %d32
156 ldd [%o0], %d34
157 ldd [%o0], %d36
158 ldd [%o0], %d38
159 ldd [%o0], %d40
160 ldd [%o0], %d42
161 ldd [%o0], %d44
162 ldd [%o0], %d46
163 ldd [%o0], %d48
164 ldd [%o0], %d50
165 ldd [%o0], %d52
166 ldd [%o0], %d54
167 ldd [%o0], %d56
168 ldd [%o0], %d58
169 ldd [%o0], %d60
170 retl
171 ldd [%o0], %d62
172 SET_SIZE(fp_clearregs)
173
174 /*
175 * void _fp_read_pfreg(pf, n)
176 * uint32_t *pf; Old freg value.
177 * unsigned n; Want to read register n
178 *
179 * {
180 * *pf = %f[n];
181 * }
182 *
183 * void
184 * _fp_write_pfreg(pf, n)
185 * uint32_t *pf; New freg value.
186 * unsigned n; Want to write register n.
187 *
188 * {
189 * %f[n] = *pf;
190 * }
191 */
192
193 ENTRY_NP(_fp_read_pfreg)
194 sll %o1, 3, %o1 ! Table entries are 8 bytes each.
195 set .stable, %g1 ! g1 gets base of table.
196 jmp %g1 + %o1 ! Jump into table
197 nop ! Can't follow CTI by CTI.
198
199 ENTRY_NP(_fp_write_pfreg)
200 sll %o1, 3, %o1 ! Table entries are 8 bytes each.
201 set .ltable, %g1 ! g1 gets base of table.
202 jmp %g1 + %o1 ! Jump into table
203 nop ! Can't follow CTI by CTI.
204
205 #define STOREFP(n) jmp %o7+8 ; st %f/**/n, [%o0]
206
207 .stable:
208 STOREFP(0)
209 STOREFP(1)
210 STOREFP(2)
211 STOREFP(3)
212 STOREFP(4)
259 LOADFP(15)
260 LOADFP(16)
261 LOADFP(17)
262 LOADFP(18)
263 LOADFP(19)
264 LOADFP(20)
265 LOADFP(21)
266 LOADFP(22)
267 LOADFP(23)
268 LOADFP(24)
269 LOADFP(25)
270 LOADFP(26)
271 LOADFP(27)
272 LOADFP(28)
273 LOADFP(29)
274 LOADFP(30)
275 LOADFP(31)
276 SET_SIZE(_fp_read_pfreg)
277 SET_SIZE(_fp_write_pfreg)
278
279 /*
280 * void _fp_read_pdreg(
281 * uint64_t *pd, Old dreg value.
282 * u_int n) Want to read register n
283 *
284 * {
285 * *pd = %d[n];
286 * }
287 *
288 * void
289 * _fp_write_pdreg(
290 * uint64_t *pd, New dreg value.
291 * u_int n) Want to write register n.
292 *
293 * {
294 * %d[n] = *pd;
295 * }
296 */
297
298 ENTRY_NP(_fp_read_pdreg)
299 sll %o1, 3, %o1 ! Table entries are 8 bytes each.
300 set .dstable, %g1 ! g1 gets base of table.
301 jmp %g1 + %o1 ! Jump into table
302 nop ! Can't follow CTI by CTI.
303
304 ENTRY_NP(_fp_write_pdreg)
305 sll %o1, 3, %o1 ! Table entries are 8 bytes each.
306 set .dltable, %g1 ! g1 gets base of table.
307 jmp %g1 + %o1 ! Jump into table
308 nop ! Can't follow CTI by CTI.
309
310 #define STOREDP(n) jmp %o7+8 ; std %d/**/n, [%o0]
311
312 .dstable:
313 STOREDP(0)
314 STOREDP(2)
315 STOREDP(4)
316 STOREDP(6)
317 STOREDP(8)
364 LOADDP(30)
365 LOADDP(32)
366 LOADDP(34)
367 LOADDP(36)
368 LOADDP(38)
369 LOADDP(40)
370 LOADDP(42)
371 LOADDP(44)
372 LOADDP(46)
373 LOADDP(48)
374 LOADDP(50)
375 LOADDP(52)
376 LOADDP(54)
377 LOADDP(56)
378 LOADDP(58)
379 LOADDP(60)
380 LOADDP(62)
381 SET_SIZE(_fp_read_pdreg)
382 SET_SIZE(_fp_write_pdreg)
383
384 ENTRY_NP(_fp_write_pfsr)
385 retl
386 ldx [%o0], %fsr
387 SET_SIZE(_fp_write_pfsr)
388
389 ENTRY_NP(_fp_read_pfsr)
390 retl
391 stx %fsr, [%o0]
392 SET_SIZE(_fp_read_pfsr)
393
394 ENTRY_NP(_fp_write_fprs)
395 retl
396 wr %o0, %g0, %fprs ! write fprs
397 SET_SIZE(_fp_write_fprs)
398
399 ENTRY_NP(_fp_read_fprs)
400 retl
401 rd %fprs, %o0 ! save fprs
402 SET_SIZE(_fp_read_fprs)
403
404 ENTRY_NP(_fp_subcc_ccr)
405 subcc %o0, %o1, %g0
406 retl
407 rd %ccr, %o0 ! save ccr
408 SET_SIZE(_fp_subcc_ccr)
409
410 /*
411 * Floating Point Exceptions handled according to type:
412 * 2) unfinished_fpop
413 * re-execute the faulty instruction(s) using
414 * software emulation (must do every instruction in FQ)
415 * 3) unimplemented_fpop
416 * an unimplemented instruction, if it is legal,
417 * will cause emulation of the instruction (and all
418 * other instuctions in the FQ)
419 * 4) sequence_error
420 * panic, this should not happen, and if it does it
421 * it is the result of a kernel bug
422 *
423 * This code assumes the trap preamble has set up the window environment
424 * for execution of kernel code.
425 * Note: this code could be changed to be part of the cpu-specific
426 * (ie, Spitfire-specific) module code before final release.
427 */
428
429 ENTRY_NP(_fp_exception)
430 mov %o7, %l0 ! saved return address
431 mov %o0, %l1 ! saved *rp
432 set FSR_FTT, %o4 ! put FSR_FTT in %o4
433 xor %o4, 0xffffffffffffffff, %o3 ! xor FSR_FTT to get
434 and %o1, %o3, %o2 ! an fsr with a zero'd ftt
435 ldn [THREAD_REG + T_LWP], %o3 ! get lwp
436 ldn [%o3 + LWP_FPU], %l3 ! get lwp_fpu
437 stx %o2, [%l3 + FPU_FSR] ! save floating point status
438 and %o1, %o4, %g2 ! get the ftt trap type
439 #ifdef DEBUG
440 brnz,a,pt %g2, fttok
441 nop
442 set .badfpfttmsg, %o0 ! panic message
443 call panic ! %o1 has the fsr w/ftt value
444 nop
445 fttok:
446 #endif /* DEBUG */
447 srl %g2, FSR_FTT_SHIFT, %o4 ! check ftt
448 cmp %o4, FTT_SEQ ! sanity check for bogus exceptions
468 ! point simulator. There is no floating point queue, so we fake one.
469 !
470 call fp_precise ! fp_precise(®s)
471 mov %l1, %o0 ! saved *rp
472
473 fp_ret:
474 rd %fprs, %g1 ! read fprs, save value in %g1
475 st %g1, [%l3 + FPU_FPRS] ! save fprs
476 jmp %l0 + 8 ! jump to saved return address
477 stx %fsr, [%l3 + FPU_FSR] ! save fsr
478 SET_SIZE(_fp_exception)
479
480 .badfpexcpmsg:
481 .asciz "unexpected floating point exception %x"
482
483 #ifdef DEBUG
484 .badfpfttmsg:
485 .asciz "No floating point ftt, fsr %llx"
486 #endif /* DEBUG */
487
488 /*
489 * Floating Point Exceptions.
490 * handled according to type:
491 * 1) IEEE_exception
492 * re-execute the faulty instruction(s) using
493 * software emulation (must do every instruction in FQ)
494 *
495 * This code assumes the trap preamble has set up the window environment
496 * for execution of kernel code.
497 */
498
499 ENTRY_NP(_fp_ieee_exception)
500 mov %o7, %l0 ! saved return address
501 mov %o0, %l1 ! saved *rp
502 mov %o1, %l2 ! saved fsr
503 set FSR_FTT, %o4 ! put FSR_FTT in %o4
504 xor %o4, 0xffffffffffffffff, %o3 ! ! xor FSR_FTT to get
505 and %o1, %o3, %o2 ! an fsr with a zero'd ftt
506 ldn [THREAD_REG + T_LWP], %o3 ! get lwp
507 ldn [%o3 + LWP_FPU], %l3 ! get lwp_fpu
508 stx %o2, [%l3 + FPU_FSR] ! save floating point status
509 stub %g0, [%l3 + FPU_QCNT] ! clear fpu_qcnt
510 and %o1, %o4, %g2 ! mask out trap type
511 #ifdef DEBUG
512 brnz,a,pt %g2, fttgd
513 nop
514 set .badfpfttmsg, %o0 ! panic message
515 call panic ! %o1 has the fsr w/ftt value
516 nop
517 fttgd:
518 #endif /* DEBUG */
565 or %g0, FPE_FLTINV, %o3 ! fp invalid code
566
567 cexec_err:
568 set .badfpcexcmsg, %o0 ! panic message
569 call panic ! panic if no cexc bit set
570 mov %g1, %o1
571 fpok:
572 mov %l1, %o0 ! saved *rp
573 call fpu_trap ! fpu_trap(®s, addr, type, code)
574 ldn [%o0 + PC_OFF], %o1 ! address of trapping instruction
575
576 rd %fprs, %g1 ! read fprs, save value in %g1
577 st %g1, [%l3 + FPU_FPRS] ! save fprs
578 jmp %l0 + 8 ! jump to saved return address
579 stx %fsr, [%l3 + FPU_FSR] ! save fsr
580 SET_SIZE(_fp_ieee_exception)
581
582 .badfpcexcmsg:
583 .asciz "No floating point exception, fsr %llx"
584
|