Print this page
de-linting of .s files


  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(&regs)
 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(&regs, 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(&regs)
 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(&regs, 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