17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7bafd143Sjb145095 * Common Development and Distribution License (the "License"). 6*7bafd143Sjb145095 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate/* 22*7bafd143Sjb145095 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate#ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 297c478bd9Sstevel@tonic-gate#include <sys/trap.h> 307c478bd9Sstevel@tonic-gate#include <sys/machpcb.h> 31*7bafd143Sjb145095#include <sys/machtrap.h> 32*7bafd143Sjb145095#include <sys/machsig.h> 33*7bafd143Sjb145095#include <sys/machthread.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate#if !defined(lint) && !defined(__lint) 367c478bd9Sstevel@tonic-gate#include "assym.h" 377c478bd9Sstevel@tonic-gate#endif /* lint */ 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate/* 407c478bd9Sstevel@tonic-gate * Floating point trap handling. 417c478bd9Sstevel@tonic-gate * 427c478bd9Sstevel@tonic-gate * The FPU is always in a V9 current configuration. 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * When a user process is first started via exec, 457c478bd9Sstevel@tonic-gate * floating point operations will be disabled by default. 467c478bd9Sstevel@tonic-gate * Upon execution of the first floating point instruction, 477c478bd9Sstevel@tonic-gate * a fp_disabled trap will be generated; then a word in 487c478bd9Sstevel@tonic-gate * the uarea is written signifying use of the floating point 497c478bd9Sstevel@tonic-gate * registers so that subsequent context switches will save 507c478bd9Sstevel@tonic-gate * and restore the floating point them. The trapped instruction 517c478bd9Sstevel@tonic-gate * will be restarted and processing will continue as normal. 527c478bd9Sstevel@tonic-gate * 537c478bd9Sstevel@tonic-gate * When a operation occurs that the hardware cannot properly 547c478bd9Sstevel@tonic-gate * handle, an unfinshed fp_op exception will be generated. 557c478bd9Sstevel@tonic-gate * Software routines in the kernel will be executed to 567c478bd9Sstevel@tonic-gate * simulate proper handling of such conditions. 577c478bd9Sstevel@tonic-gate * 587c478bd9Sstevel@tonic-gate * Exception handling will emulate all instructions 597c478bd9Sstevel@tonic-gate * in the floating point address queue. Note that there 607c478bd9Sstevel@tonic-gate * is no %fq in sun4u, because it has precise FP traps. 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * Floating point queues are now machine dependent, and std %fq 637c478bd9Sstevel@tonic-gate * is an illegal V9 instruction. The fp_exception code has been 647c478bd9Sstevel@tonic-gate * moved to sun4u/ml/machfloat.s. 657c478bd9Sstevel@tonic-gate * 667c478bd9Sstevel@tonic-gate * NOTE: This code DOES NOT SUPPORT KERNEL (DEVICE DRIVER) 677c478bd9Sstevel@tonic-gate * USE OF THE FPU 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * Instructions for running without the hardware fpu: 707c478bd9Sstevel@tonic-gate * 1. Setting fpu_exists to 0 now only works on a DEBUG kernel. 717c478bd9Sstevel@tonic-gate * 2. adb -w unix and set fpu_exists, use_hw_bcopy, use_hw_copyio, and 727c478bd9Sstevel@tonic-gate * use_hw_bzero to 0 and rename libc_psr.so.1 in 737c478bd9Sstevel@tonic-gate * /usr/platform/sun4u/lib so that it will not get used by 747c478bd9Sstevel@tonic-gate * the libc bcopy routines. Then reboot the system and you 757c478bd9Sstevel@tonic-gate * should see the bootup message "FPU not in use". 767c478bd9Sstevel@tonic-gate * 3. To run kaos, you must comment out the code which sets the 777c478bd9Sstevel@tonic-gate * version number of the fsr to 7, in fldst: stfsr/stxfsr 787c478bd9Sstevel@tonic-gate * (unless you are running against a comparison system that 797c478bd9Sstevel@tonic-gate * has the same fsr version number). 807c478bd9Sstevel@tonic-gate * 4. The stqf{a}/ldqf{a} instructions cause kaos errors, for reasons 817c478bd9Sstevel@tonic-gate * that appear to be a kaos bug, so don't use them! 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate#ifdef FP_DISABLED 877c478bd9Sstevel@tonic-gateint fpu_exists = 0; 887c478bd9Sstevel@tonic-gate#else 897c478bd9Sstevel@tonic-gateint fpu_exists = 1; 907c478bd9Sstevel@tonic-gate#endif 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate#else /* lint */ 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate .section ".data" 957c478bd9Sstevel@tonic-gate .align 8 967c478bd9Sstevel@tonic-gatefsrholder: 977c478bd9Sstevel@tonic-gate .word 0 ! dummy place to write fsr 987c478bd9Sstevel@tonic-gate .word 0 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate DGDEF(fpu_exists) ! always exists for V9 1017c478bd9Sstevel@tonic-gate#ifdef FP_DISABLED 1027c478bd9Sstevel@tonic-gate .word 0 1037c478bd9Sstevel@tonic-gate#else 1047c478bd9Sstevel@tonic-gate .word 1 ! sundiag (gack) uses this variable 1057c478bd9Sstevel@tonic-gate#endif 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate DGDEF(fpu_version) 1087c478bd9Sstevel@tonic-gate .word -1 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate#endif /* lint */ 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate/* 1137c478bd9Sstevel@tonic-gate * FPU probe - read the %fsr and get fpu_version. 1147c478bd9Sstevel@tonic-gate * Called from autoconf. If a %fq is created for 1157c478bd9Sstevel@tonic-gate * future cpu versions, a fq_exists variable 1167c478bd9Sstevel@tonic-gate * could be created by this function. 1177c478bd9Sstevel@tonic-gate */ 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 1227c478bd9Sstevel@tonic-gatevoid 1237c478bd9Sstevel@tonic-gatefpu_probe(void) 1247c478bd9Sstevel@tonic-gate{} 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate#else /* lint */ 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate ENTRY_NP(fpu_probe) 1297c478bd9Sstevel@tonic-gate wr %g0, FPRS_FEF, %fprs ! enable fpu in fprs 1307c478bd9Sstevel@tonic-gate rdpr %pstate, %g2 ! read pstate, save value in %g2 1317c478bd9Sstevel@tonic-gate or %g2, PSTATE_PEF, %g1 ! new pstate with fpu enabled 1327c478bd9Sstevel@tonic-gate wrpr %g1, %g0, %pstate ! write pstate 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate sethi %hi(fsrholder), %g2 1357c478bd9Sstevel@tonic-gate stx %fsr, [%g2 + %lo(fsrholder)] 1367c478bd9Sstevel@tonic-gate ldx [%g2 + %lo(fsrholder)], %g2 ! snarf the FSR 1377c478bd9Sstevel@tonic-gate set FSR_VER, %g1 1387c478bd9Sstevel@tonic-gate and %g2, %g1, %g2 ! get version 1397c478bd9Sstevel@tonic-gate srl %g2, FSR_VER_SHIFT, %g2 ! and shift it down 1407c478bd9Sstevel@tonic-gate sethi %hi(fpu_version), %g3 ! save the FPU version 1417c478bd9Sstevel@tonic-gate st %g2, [%g3 + %lo(fpu_version)] 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate ba fp_kstat_init ! initialize the fpu_kstat 1447c478bd9Sstevel@tonic-gate wr %g0, %g0, %fprs ! disable fpu and clear fprs 1457c478bd9Sstevel@tonic-gate SET_SIZE(fpu_probe) 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate#endif /* lint */ 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate/* 1507c478bd9Sstevel@tonic-gate * fp_clearregs(fp) 1517c478bd9Sstevel@tonic-gate * struct v9_fpu *fp; 1527c478bd9Sstevel@tonic-gate * 1537c478bd9Sstevel@tonic-gate * Initialization for the hardware fpu. 1547c478bd9Sstevel@tonic-gate * Clear the fsr and initialize registers to NaN (-1) 1557c478bd9Sstevel@tonic-gate * The caller (fp_disabled) is supposed to update the fprs 1567c478bd9Sstevel@tonic-gate * so when the return to userland is made, the fpu is enabled. 1577c478bd9Sstevel@tonic-gate */ 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 1627c478bd9Sstevel@tonic-gatevoid 1637c478bd9Sstevel@tonic-gatefp_clearregs(kfpu_t *fp) 1647c478bd9Sstevel@tonic-gate{} 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate#else /* lint */ 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate ENTRY_NP(fp_clearregs) 1697c478bd9Sstevel@tonic-gate ldx [%o0 + FPU_FSR], %fsr ! load fsr 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate mov -1, %g2 ! -1 is NaN 1727c478bd9Sstevel@tonic-gate stx %g2, [%o0] ! initialize %f0 1737c478bd9Sstevel@tonic-gate ldd [%o0], %d0 1747c478bd9Sstevel@tonic-gate ldd [%o0], %d2 1757c478bd9Sstevel@tonic-gate ldd [%o0], %d4 1767c478bd9Sstevel@tonic-gate ldd [%o0], %d6 1777c478bd9Sstevel@tonic-gate ldd [%o0], %d8 1787c478bd9Sstevel@tonic-gate ldd [%o0], %d10 1797c478bd9Sstevel@tonic-gate ldd [%o0], %d12 1807c478bd9Sstevel@tonic-gate ldd [%o0], %d14 1817c478bd9Sstevel@tonic-gate ldd [%o0], %d16 1827c478bd9Sstevel@tonic-gate ldd [%o0], %d18 1837c478bd9Sstevel@tonic-gate ldd [%o0], %d20 1847c478bd9Sstevel@tonic-gate ldd [%o0], %d22 1857c478bd9Sstevel@tonic-gate ldd [%o0], %d24 1867c478bd9Sstevel@tonic-gate ldd [%o0], %d26 1877c478bd9Sstevel@tonic-gate ldd [%o0], %d28 1887c478bd9Sstevel@tonic-gate ldd [%o0], %d30 1897c478bd9Sstevel@tonic-gate ldd [%o0], %d32 1907c478bd9Sstevel@tonic-gate ldd [%o0], %d34 1917c478bd9Sstevel@tonic-gate ldd [%o0], %d36 1927c478bd9Sstevel@tonic-gate ldd [%o0], %d38 1937c478bd9Sstevel@tonic-gate ldd [%o0], %d40 1947c478bd9Sstevel@tonic-gate ldd [%o0], %d42 1957c478bd9Sstevel@tonic-gate ldd [%o0], %d44 1967c478bd9Sstevel@tonic-gate ldd [%o0], %d46 1977c478bd9Sstevel@tonic-gate ldd [%o0], %d48 1987c478bd9Sstevel@tonic-gate ldd [%o0], %d50 1997c478bd9Sstevel@tonic-gate ldd [%o0], %d52 2007c478bd9Sstevel@tonic-gate ldd [%o0], %d54 2017c478bd9Sstevel@tonic-gate ldd [%o0], %d56 2027c478bd9Sstevel@tonic-gate ldd [%o0], %d58 2037c478bd9Sstevel@tonic-gate ldd [%o0], %d60 2047c478bd9Sstevel@tonic-gate retl 2057c478bd9Sstevel@tonic-gate ldd [%o0], %d62 2067c478bd9Sstevel@tonic-gate SET_SIZE(fp_clearregs) 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate#endif /* lint */ 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate/* 2117c478bd9Sstevel@tonic-gate * void _fp_read_pfreg(pf, n) 2127c478bd9Sstevel@tonic-gate * uint32_t *pf; Old freg value. 2137c478bd9Sstevel@tonic-gate * unsigned n; Want to read register n 2147c478bd9Sstevel@tonic-gate * 2157c478bd9Sstevel@tonic-gate * { 2167c478bd9Sstevel@tonic-gate * *pf = %f[n]; 2177c478bd9Sstevel@tonic-gate * } 2187c478bd9Sstevel@tonic-gate * 2197c478bd9Sstevel@tonic-gate * void 2207c478bd9Sstevel@tonic-gate * _fp_write_pfreg(pf, n) 2217c478bd9Sstevel@tonic-gate * uint32_t *pf; New freg value. 2227c478bd9Sstevel@tonic-gate * unsigned n; Want to write register n. 2237c478bd9Sstevel@tonic-gate * 2247c478bd9Sstevel@tonic-gate * { 2257c478bd9Sstevel@tonic-gate * %f[n] = *pf; 2267c478bd9Sstevel@tonic-gate * } 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 2327c478bd9Sstevel@tonic-gatevoid 2337c478bd9Sstevel@tonic-gate_fp_read_pfreg(uint32_t *pf, u_int n) 2347c478bd9Sstevel@tonic-gate{} 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 2377c478bd9Sstevel@tonic-gatevoid 2387c478bd9Sstevel@tonic-gate_fp_write_pfreg(uint32_t *pf, u_int n) 2397c478bd9Sstevel@tonic-gate{} 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate#else /* lint */ 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_read_pfreg) 2447c478bd9Sstevel@tonic-gate sll %o1, 3, %o1 ! Table entries are 8 bytes each. 2457c478bd9Sstevel@tonic-gate set .stable, %g1 ! g1 gets base of table. 2467c478bd9Sstevel@tonic-gate jmp %g1 + %o1 ! Jump into table 2477c478bd9Sstevel@tonic-gate nop ! Can't follow CTI by CTI. 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_write_pfreg) 2507c478bd9Sstevel@tonic-gate sll %o1, 3, %o1 ! Table entries are 8 bytes each. 2517c478bd9Sstevel@tonic-gate set .ltable, %g1 ! g1 gets base of table. 2527c478bd9Sstevel@tonic-gate jmp %g1 + %o1 ! Jump into table 2537c478bd9Sstevel@tonic-gate nop ! Can't follow CTI by CTI. 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate#define STOREFP(n) jmp %o7+8 ; st %f/**/n, [%o0] 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate.stable: 2587c478bd9Sstevel@tonic-gate STOREFP(0) 2597c478bd9Sstevel@tonic-gate STOREFP(1) 2607c478bd9Sstevel@tonic-gate STOREFP(2) 2617c478bd9Sstevel@tonic-gate STOREFP(3) 2627c478bd9Sstevel@tonic-gate STOREFP(4) 2637c478bd9Sstevel@tonic-gate STOREFP(5) 2647c478bd9Sstevel@tonic-gate STOREFP(6) 2657c478bd9Sstevel@tonic-gate STOREFP(7) 2667c478bd9Sstevel@tonic-gate STOREFP(8) 2677c478bd9Sstevel@tonic-gate STOREFP(9) 2687c478bd9Sstevel@tonic-gate STOREFP(10) 2697c478bd9Sstevel@tonic-gate STOREFP(11) 2707c478bd9Sstevel@tonic-gate STOREFP(12) 2717c478bd9Sstevel@tonic-gate STOREFP(13) 2727c478bd9Sstevel@tonic-gate STOREFP(14) 2737c478bd9Sstevel@tonic-gate STOREFP(15) 2747c478bd9Sstevel@tonic-gate STOREFP(16) 2757c478bd9Sstevel@tonic-gate STOREFP(17) 2767c478bd9Sstevel@tonic-gate STOREFP(18) 2777c478bd9Sstevel@tonic-gate STOREFP(19) 2787c478bd9Sstevel@tonic-gate STOREFP(20) 2797c478bd9Sstevel@tonic-gate STOREFP(21) 2807c478bd9Sstevel@tonic-gate STOREFP(22) 2817c478bd9Sstevel@tonic-gate STOREFP(23) 2827c478bd9Sstevel@tonic-gate STOREFP(24) 2837c478bd9Sstevel@tonic-gate STOREFP(25) 2847c478bd9Sstevel@tonic-gate STOREFP(26) 2857c478bd9Sstevel@tonic-gate STOREFP(27) 2867c478bd9Sstevel@tonic-gate STOREFP(28) 2877c478bd9Sstevel@tonic-gate STOREFP(29) 2887c478bd9Sstevel@tonic-gate STOREFP(30) 2897c478bd9Sstevel@tonic-gate STOREFP(31) 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate#define LOADFP(n) jmp %o7+8 ; ld [%o0],%f/**/n 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate.ltable: 2947c478bd9Sstevel@tonic-gate LOADFP(0) 2957c478bd9Sstevel@tonic-gate LOADFP(1) 2967c478bd9Sstevel@tonic-gate LOADFP(2) 2977c478bd9Sstevel@tonic-gate LOADFP(3) 2987c478bd9Sstevel@tonic-gate LOADFP(4) 2997c478bd9Sstevel@tonic-gate LOADFP(5) 3007c478bd9Sstevel@tonic-gate LOADFP(6) 3017c478bd9Sstevel@tonic-gate LOADFP(7) 3027c478bd9Sstevel@tonic-gate LOADFP(8) 3037c478bd9Sstevel@tonic-gate LOADFP(9) 3047c478bd9Sstevel@tonic-gate LOADFP(10) 3057c478bd9Sstevel@tonic-gate LOADFP(11) 3067c478bd9Sstevel@tonic-gate LOADFP(12) 3077c478bd9Sstevel@tonic-gate LOADFP(13) 3087c478bd9Sstevel@tonic-gate LOADFP(14) 3097c478bd9Sstevel@tonic-gate LOADFP(15) 3107c478bd9Sstevel@tonic-gate LOADFP(16) 3117c478bd9Sstevel@tonic-gate LOADFP(17) 3127c478bd9Sstevel@tonic-gate LOADFP(18) 3137c478bd9Sstevel@tonic-gate LOADFP(19) 3147c478bd9Sstevel@tonic-gate LOADFP(20) 3157c478bd9Sstevel@tonic-gate LOADFP(21) 3167c478bd9Sstevel@tonic-gate LOADFP(22) 3177c478bd9Sstevel@tonic-gate LOADFP(23) 3187c478bd9Sstevel@tonic-gate LOADFP(24) 3197c478bd9Sstevel@tonic-gate LOADFP(25) 3207c478bd9Sstevel@tonic-gate LOADFP(26) 3217c478bd9Sstevel@tonic-gate LOADFP(27) 3227c478bd9Sstevel@tonic-gate LOADFP(28) 3237c478bd9Sstevel@tonic-gate LOADFP(29) 3247c478bd9Sstevel@tonic-gate LOADFP(30) 3257c478bd9Sstevel@tonic-gate LOADFP(31) 3267c478bd9Sstevel@tonic-gate SET_SIZE(_fp_read_pfreg) 3277c478bd9Sstevel@tonic-gate SET_SIZE(_fp_write_pfreg) 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate#endif /* lint */ 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate/* 3327c478bd9Sstevel@tonic-gate * void _fp_read_pdreg( 3337c478bd9Sstevel@tonic-gate * uint64_t *pd, Old dreg value. 3347c478bd9Sstevel@tonic-gate * u_int n) Want to read register n 3357c478bd9Sstevel@tonic-gate * 3367c478bd9Sstevel@tonic-gate * { 3377c478bd9Sstevel@tonic-gate * *pd = %d[n]; 3387c478bd9Sstevel@tonic-gate * } 3397c478bd9Sstevel@tonic-gate * 3407c478bd9Sstevel@tonic-gate * void 3417c478bd9Sstevel@tonic-gate * _fp_write_pdreg( 3427c478bd9Sstevel@tonic-gate * uint64_t *pd, New dreg value. 3437c478bd9Sstevel@tonic-gate * u_int n) Want to write register n. 3447c478bd9Sstevel@tonic-gate * 3457c478bd9Sstevel@tonic-gate * { 3467c478bd9Sstevel@tonic-gate * %d[n] = *pd; 3477c478bd9Sstevel@tonic-gate * } 3487c478bd9Sstevel@tonic-gate */ 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3537c478bd9Sstevel@tonic-gatevoid 3547c478bd9Sstevel@tonic-gate_fp_read_pdreg(uint64_t *pd, u_int n) 3557c478bd9Sstevel@tonic-gate{} 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3587c478bd9Sstevel@tonic-gatevoid 3597c478bd9Sstevel@tonic-gate_fp_write_pdreg(uint64_t *pd, u_int n) 3607c478bd9Sstevel@tonic-gate{} 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate#else /* lint */ 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_read_pdreg) 3657c478bd9Sstevel@tonic-gate sll %o1, 3, %o1 ! Table entries are 8 bytes each. 3667c478bd9Sstevel@tonic-gate set .dstable, %g1 ! g1 gets base of table. 3677c478bd9Sstevel@tonic-gate jmp %g1 + %o1 ! Jump into table 3687c478bd9Sstevel@tonic-gate nop ! Can't follow CTI by CTI. 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_write_pdreg) 3717c478bd9Sstevel@tonic-gate sll %o1, 3, %o1 ! Table entries are 8 bytes each. 3727c478bd9Sstevel@tonic-gate set .dltable, %g1 ! g1 gets base of table. 3737c478bd9Sstevel@tonic-gate jmp %g1 + %o1 ! Jump into table 3747c478bd9Sstevel@tonic-gate nop ! Can't follow CTI by CTI. 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate#define STOREDP(n) jmp %o7+8 ; std %d/**/n, [%o0] 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate.dstable: 3797c478bd9Sstevel@tonic-gate STOREDP(0) 3807c478bd9Sstevel@tonic-gate STOREDP(2) 3817c478bd9Sstevel@tonic-gate STOREDP(4) 3827c478bd9Sstevel@tonic-gate STOREDP(6) 3837c478bd9Sstevel@tonic-gate STOREDP(8) 3847c478bd9Sstevel@tonic-gate STOREDP(10) 3857c478bd9Sstevel@tonic-gate STOREDP(12) 3867c478bd9Sstevel@tonic-gate STOREDP(14) 3877c478bd9Sstevel@tonic-gate STOREDP(16) 3887c478bd9Sstevel@tonic-gate STOREDP(18) 3897c478bd9Sstevel@tonic-gate STOREDP(20) 3907c478bd9Sstevel@tonic-gate STOREDP(22) 3917c478bd9Sstevel@tonic-gate STOREDP(24) 3927c478bd9Sstevel@tonic-gate STOREDP(26) 3937c478bd9Sstevel@tonic-gate STOREDP(28) 3947c478bd9Sstevel@tonic-gate STOREDP(30) 3957c478bd9Sstevel@tonic-gate STOREDP(32) 3967c478bd9Sstevel@tonic-gate STOREDP(34) 3977c478bd9Sstevel@tonic-gate STOREDP(36) 3987c478bd9Sstevel@tonic-gate STOREDP(38) 3997c478bd9Sstevel@tonic-gate STOREDP(40) 4007c478bd9Sstevel@tonic-gate STOREDP(42) 4017c478bd9Sstevel@tonic-gate STOREDP(44) 4027c478bd9Sstevel@tonic-gate STOREDP(46) 4037c478bd9Sstevel@tonic-gate STOREDP(48) 4047c478bd9Sstevel@tonic-gate STOREDP(50) 4057c478bd9Sstevel@tonic-gate STOREDP(52) 4067c478bd9Sstevel@tonic-gate STOREDP(54) 4077c478bd9Sstevel@tonic-gate STOREDP(56) 4087c478bd9Sstevel@tonic-gate STOREDP(58) 4097c478bd9Sstevel@tonic-gate STOREDP(60) 4107c478bd9Sstevel@tonic-gate STOREDP(62) 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate#define LOADDP(n) jmp %o7+8 ; ldd [%o0],%d/**/n 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate.dltable: 4157c478bd9Sstevel@tonic-gate LOADDP(0) 4167c478bd9Sstevel@tonic-gate LOADDP(2) 4177c478bd9Sstevel@tonic-gate LOADDP(4) 4187c478bd9Sstevel@tonic-gate LOADDP(6) 4197c478bd9Sstevel@tonic-gate LOADDP(8) 4207c478bd9Sstevel@tonic-gate LOADDP(10) 4217c478bd9Sstevel@tonic-gate LOADDP(12) 4227c478bd9Sstevel@tonic-gate LOADDP(14) 4237c478bd9Sstevel@tonic-gate LOADDP(16) 4247c478bd9Sstevel@tonic-gate LOADDP(18) 4257c478bd9Sstevel@tonic-gate LOADDP(20) 4267c478bd9Sstevel@tonic-gate LOADDP(22) 4277c478bd9Sstevel@tonic-gate LOADDP(24) 4287c478bd9Sstevel@tonic-gate LOADDP(26) 4297c478bd9Sstevel@tonic-gate LOADDP(28) 4307c478bd9Sstevel@tonic-gate LOADDP(30) 4317c478bd9Sstevel@tonic-gate LOADDP(32) 4327c478bd9Sstevel@tonic-gate LOADDP(34) 4337c478bd9Sstevel@tonic-gate LOADDP(36) 4347c478bd9Sstevel@tonic-gate LOADDP(38) 4357c478bd9Sstevel@tonic-gate LOADDP(40) 4367c478bd9Sstevel@tonic-gate LOADDP(42) 4377c478bd9Sstevel@tonic-gate LOADDP(44) 4387c478bd9Sstevel@tonic-gate LOADDP(46) 4397c478bd9Sstevel@tonic-gate LOADDP(48) 4407c478bd9Sstevel@tonic-gate LOADDP(50) 4417c478bd9Sstevel@tonic-gate LOADDP(52) 4427c478bd9Sstevel@tonic-gate LOADDP(54) 4437c478bd9Sstevel@tonic-gate LOADDP(56) 4447c478bd9Sstevel@tonic-gate LOADDP(58) 4457c478bd9Sstevel@tonic-gate LOADDP(60) 4467c478bd9Sstevel@tonic-gate LOADDP(62) 4477c478bd9Sstevel@tonic-gate SET_SIZE(_fp_read_pdreg) 4487c478bd9Sstevel@tonic-gate SET_SIZE(_fp_write_pdreg) 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate#endif /* lint */ 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4557c478bd9Sstevel@tonic-gatevoid 4567c478bd9Sstevel@tonic-gate_fp_write_pfsr(uint64_t *fsr) 4577c478bd9Sstevel@tonic-gate{} 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate#else /* lint */ 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_write_pfsr) 4627c478bd9Sstevel@tonic-gate retl 4637c478bd9Sstevel@tonic-gate ldx [%o0], %fsr 4647c478bd9Sstevel@tonic-gate SET_SIZE(_fp_write_pfsr) 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate#endif /* lint */ 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4717c478bd9Sstevel@tonic-gatevoid 4727c478bd9Sstevel@tonic-gate_fp_read_pfsr(uint64_t *fsr) 4737c478bd9Sstevel@tonic-gate{} 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate#else /* lint */ 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_read_pfsr) 4787c478bd9Sstevel@tonic-gate retl 4797c478bd9Sstevel@tonic-gate stx %fsr, [%o0] 4807c478bd9Sstevel@tonic-gate SET_SIZE(_fp_read_pfsr) 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate#endif /* lint */ 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4877c478bd9Sstevel@tonic-gatevoid 4887c478bd9Sstevel@tonic-gate_fp_write_fprs(u_int fprs_val) 4897c478bd9Sstevel@tonic-gate{} 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate#else /* lint */ 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_write_fprs) 4947c478bd9Sstevel@tonic-gate retl 4957c478bd9Sstevel@tonic-gate wr %o0, %g0, %fprs ! write fprs 4967c478bd9Sstevel@tonic-gate SET_SIZE(_fp_write_fprs) 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate#endif /* lint */ 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gateunsigned 5037c478bd9Sstevel@tonic-gate_fp_read_fprs(void) 5047c478bd9Sstevel@tonic-gate{return 0;} 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate#else /* lint */ 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_read_fprs) 5097c478bd9Sstevel@tonic-gate retl 5107c478bd9Sstevel@tonic-gate rd %fprs, %o0 ! save fprs 5117c478bd9Sstevel@tonic-gate SET_SIZE(_fp_read_fprs) 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate#endif /* lint */ 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint) 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gateunsigned 5187c478bd9Sstevel@tonic-gate_fp_subcc_ccr(void) 5197c478bd9Sstevel@tonic-gate{return 0;} 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate#else /* lint */ 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate ENTRY_NP(_fp_subcc_ccr) 5247c478bd9Sstevel@tonic-gate subcc %o0, %o1, %g0 5257c478bd9Sstevel@tonic-gate retl 5267c478bd9Sstevel@tonic-gate rd %ccr, %o0 ! save ccr 5277c478bd9Sstevel@tonic-gate SET_SIZE(_fp_subcc_ccr) 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate#endif /* lint */ 530*7bafd143Sjb145095 531*7bafd143Sjb145095/* 532*7bafd143Sjb145095 * Floating Point Exceptions handled according to type: 533*7bafd143Sjb145095 * 2) unfinished_fpop 534*7bafd143Sjb145095 * re-execute the faulty instruction(s) using 535*7bafd143Sjb145095 * software emulation (must do every instruction in FQ) 536*7bafd143Sjb145095 * 3) unimplemented_fpop 537*7bafd143Sjb145095 * an unimplemented instruction, if it is legal, 538*7bafd143Sjb145095 * will cause emulation of the instruction (and all 539*7bafd143Sjb145095 * other instuctions in the FQ) 540*7bafd143Sjb145095 * 4) sequence_error 541*7bafd143Sjb145095 * panic, this should not happen, and if it does it 542*7bafd143Sjb145095 * it is the result of a kernel bug 543*7bafd143Sjb145095 * 544*7bafd143Sjb145095 * This code assumes the trap preamble has set up the window environment 545*7bafd143Sjb145095 * for execution of kernel code. 546*7bafd143Sjb145095 * Note: this code could be changed to be part of the cpu-specific 547*7bafd143Sjb145095 * (ie, Spitfire-specific) module code before final release. 548*7bafd143Sjb145095 */ 549*7bafd143Sjb145095 550*7bafd143Sjb145095#if defined(lint) 551*7bafd143Sjb145095 552*7bafd143Sjb145095/* ARGSUSED */ 553*7bafd143Sjb145095void 554*7bafd143Sjb145095_fp_exception(struct regs *rp, uint64_t fsr) 555*7bafd143Sjb145095{} 556*7bafd143Sjb145095 557*7bafd143Sjb145095#else /* lint */ 558*7bafd143Sjb145095 559*7bafd143Sjb145095 ENTRY_NP(_fp_exception) 560*7bafd143Sjb145095 mov %o7, %l0 ! saved return address 561*7bafd143Sjb145095 mov %o0, %l1 ! saved *rp 562*7bafd143Sjb145095 set FSR_FTT, %o4 ! put FSR_FTT in %o4 563*7bafd143Sjb145095 xor %o4, 0xffffffffffffffff, %o3 ! xor FSR_FTT to get 564*7bafd143Sjb145095 and %o1, %o3, %o2 ! an fsr with a zero'd ftt 565*7bafd143Sjb145095 ldn [THREAD_REG + T_LWP], %o3 ! get lwp 566*7bafd143Sjb145095 ldn [%o3 + LWP_FPU], %l3 ! get lwp_fpu 567*7bafd143Sjb145095 stx %o2, [%l3 + FPU_FSR] ! save floating point status 568*7bafd143Sjb145095 and %o1, %o4, %g2 ! get the ftt trap type 569*7bafd143Sjb145095#ifdef DEBUG 570*7bafd143Sjb145095 brnz,a,pt %g2, fttok 571*7bafd143Sjb145095 nop 572*7bafd143Sjb145095 set .badfpfttmsg, %o0 ! panic message 573*7bafd143Sjb145095 call panic ! %o1 has the fsr w/ftt value 574*7bafd143Sjb145095 nop 575*7bafd143Sjb145095fttok: 576*7bafd143Sjb145095#endif /* DEBUG */ 577*7bafd143Sjb145095 srl %g2, FSR_FTT_SHIFT, %o4 ! check ftt 578*7bafd143Sjb145095 cmp %o4, FTT_SEQ ! sanity check for bogus exceptions 579*7bafd143Sjb145095 ! 580*7bafd143Sjb145095 ! traps are already enabled to allow other 581*7bafd143Sjb145095 ! interrupts while emulating floating point instructions 582*7bafd143Sjb145095 ! 583*7bafd143Sjb145095 blt,a,pt %xcc, fpeok 584*7bafd143Sjb145095 nop 585*7bafd143Sjb145095 ! 586*7bafd143Sjb145095 ! Sequence error or unknown ftt exception. 587*7bafd143Sjb145095 ! 588*7bafd143Sjb145095seq_error: 589*7bafd143Sjb145095 set .badfpexcpmsg, %o0 ! panic if bad ftt 590*7bafd143Sjb145095 call panic 591*7bafd143Sjb145095 sra %o4, 0, %o1 ! mov ftt to o1 for panic message 592*7bafd143Sjb145095 593*7bafd143Sjb145095fpeok: 594*7bafd143Sjb145095 call fp_kstat_update ! fp_kstat_update(ftt) 595*7bafd143Sjb145095 mov %o4, %o0 ! ftt 596*7bafd143Sjb145095 ! 597*7bafd143Sjb145095 ! Get the floating point instruction, and run the floating 598*7bafd143Sjb145095 ! point simulator. There is no floating point queue, so we fake one. 599*7bafd143Sjb145095 ! 600*7bafd143Sjb145095 call fp_precise ! fp_precise(®s) 601*7bafd143Sjb145095 mov %l1, %o0 ! saved *rp 602*7bafd143Sjb145095 603*7bafd143Sjb145095fp_ret: 604*7bafd143Sjb145095 rd %fprs, %g1 ! read fprs, save value in %g1 605*7bafd143Sjb145095 st %g1, [%l3 + FPU_FPRS] ! save fprs 606*7bafd143Sjb145095 jmp %l0 + 8 ! jump to saved return address 607*7bafd143Sjb145095 stx %fsr, [%l3 + FPU_FSR] ! save fsr 608*7bafd143Sjb145095 SET_SIZE(_fp_exception) 609*7bafd143Sjb145095 610*7bafd143Sjb145095.badfpexcpmsg: 611*7bafd143Sjb145095 .asciz "unexpected floating point exception %x" 612*7bafd143Sjb145095 613*7bafd143Sjb145095#ifdef DEBUG 614*7bafd143Sjb145095.badfpfttmsg: 615*7bafd143Sjb145095 .asciz "No floating point ftt, fsr %llx" 616*7bafd143Sjb145095#endif /* DEBUG */ 617*7bafd143Sjb145095 618*7bafd143Sjb145095#endif /* lint */ 619*7bafd143Sjb145095 620*7bafd143Sjb145095/* 621*7bafd143Sjb145095 * Floating Point Exceptions. 622*7bafd143Sjb145095 * handled according to type: 623*7bafd143Sjb145095 * 1) IEEE_exception 624*7bafd143Sjb145095 * re-execute the faulty instruction(s) using 625*7bafd143Sjb145095 * software emulation (must do every instruction in FQ) 626*7bafd143Sjb145095 * 627*7bafd143Sjb145095 * This code assumes the trap preamble has set up the window environment 628*7bafd143Sjb145095 * for execution of kernel code. 629*7bafd143Sjb145095 */ 630*7bafd143Sjb145095 631*7bafd143Sjb145095#if defined(lint) 632*7bafd143Sjb145095 633*7bafd143Sjb145095/* ARGSUSED */ 634*7bafd143Sjb145095void 635*7bafd143Sjb145095_fp_ieee_exception(struct regs *rp, uint64_t fsr) 636*7bafd143Sjb145095{} 637*7bafd143Sjb145095 638*7bafd143Sjb145095#else /* lint */ 639*7bafd143Sjb145095 640*7bafd143Sjb145095 ENTRY_NP(_fp_ieee_exception) 641*7bafd143Sjb145095 mov %o7, %l0 ! saved return address 642*7bafd143Sjb145095 mov %o0, %l1 ! saved *rp 643*7bafd143Sjb145095 mov %o1, %l2 ! saved fsr 644*7bafd143Sjb145095 set FSR_FTT, %o4 ! put FSR_FTT in %o4 645*7bafd143Sjb145095 xor %o4, 0xffffffffffffffff, %o3 ! ! xor FSR_FTT to get 646*7bafd143Sjb145095 and %o1, %o3, %o2 ! an fsr with a zero'd ftt 647*7bafd143Sjb145095 ldn [THREAD_REG + T_LWP], %o3 ! get lwp 648*7bafd143Sjb145095 ldn [%o3 + LWP_FPU], %l3 ! get lwp_fpu 649*7bafd143Sjb145095 stx %o2, [%l3 + FPU_FSR] ! save floating point status 650*7bafd143Sjb145095 stub %g0, [%l3 + FPU_QCNT] ! clear fpu_qcnt 651*7bafd143Sjb145095 and %o1, %o4, %g2 ! mask out trap type 652*7bafd143Sjb145095#ifdef DEBUG 653*7bafd143Sjb145095 brnz,a,pt %g2, fttgd 654*7bafd143Sjb145095 nop 655*7bafd143Sjb145095 set .badfpfttmsg, %o0 ! panic message 656*7bafd143Sjb145095 call panic ! %o1 has the fsr w/ftt value 657*7bafd143Sjb145095 nop 658*7bafd143Sjb145095fttgd: 659*7bafd143Sjb145095#endif /* DEBUG */ 660*7bafd143Sjb145095 srl %g2, FSR_FTT_SHIFT, %o4 ! check ftt 661*7bafd143Sjb145095 cmp %o4, FTT_SEQ ! sanity check for bogus exceptions 662*7bafd143Sjb145095 ! 663*7bafd143Sjb145095 ! traps are already enabled to allow other 664*7bafd143Sjb145095 ! interrupts while emulating floating point instructions 665*7bafd143Sjb145095 ! 666*7bafd143Sjb145095 blt,a,pt %xcc, fpegd 667*7bafd143Sjb145095 nop 668*7bafd143Sjb145095 ! 669*7bafd143Sjb145095 ! Sequence error or unknown ftt exception. 670*7bafd143Sjb145095 ! 671*7bafd143Sjb145095seq_err: 672*7bafd143Sjb145095 set .badfpexcpmsg, %o0 ! panic if bad ftt 673*7bafd143Sjb145095 call panic 674*7bafd143Sjb145095 sra %o4, 0, %o1 ! mov ftt to o1 for panic message 675*7bafd143Sjb145095 676*7bafd143Sjb145095fpegd: 677*7bafd143Sjb145095 call fp_kstat_update ! fp_kstat_update(ftt) 678*7bafd143Sjb145095 mov %o4, %o0 ! ftt 679*7bafd143Sjb145095 ! 680*7bafd143Sjb145095 ! Call fpu_trap directly, don't bother to run the fp simulator. 681*7bafd143Sjb145095 ! The *rp is already in %o0. Clear fpu_qcnt. 682*7bafd143Sjb145095 ! 683*7bafd143Sjb145095 set (T_FP_EXCEPTION_IEEE), %o2 ! trap type 684*7bafd143Sjb145095 685*7bafd143Sjb145095 set FSR_CEXC, %o3 686*7bafd143Sjb145095 and %l2, %o3, %g2 ! mask out cexc 687*7bafd143Sjb145095 688*7bafd143Sjb145095 andcc %g2, FSR_CEXC_NX, %g0 ! check for inexact 689*7bafd143Sjb145095 bnz,a,pt %xcc, fpok 690*7bafd143Sjb145095 or %g0, FPE_FLTRES, %o3 ! fp inexact code 691*7bafd143Sjb145095 692*7bafd143Sjb145095 andcc %g2, FSR_CEXC_DZ, %g0 ! check for divide-by-zero 693*7bafd143Sjb145095 bnz,a,pt %xcc, fpok 694*7bafd143Sjb145095 or %g0, FPE_FLTDIV, %o3 ! fp divide by zero code 695*7bafd143Sjb145095 696*7bafd143Sjb145095 andcc %g2, FSR_CEXC_UF, %g0 ! check for underflow 697*7bafd143Sjb145095 bnz,a,pt %xcc, fpok 698*7bafd143Sjb145095 or %g0, FPE_FLTUND, %o3 ! fp underflow code 699*7bafd143Sjb145095 700*7bafd143Sjb145095 andcc %g2, FSR_CEXC_OF, %g0 ! check for overflow 701*7bafd143Sjb145095 bnz,a,pt %xcc, fpok 702*7bafd143Sjb145095 or %g0, FPE_FLTOVF, %o3 ! fp overflow code 703*7bafd143Sjb145095 704*7bafd143Sjb145095 andcc %g2, FSR_CEXC_NV, %g0 ! check for invalid 705*7bafd143Sjb145095 bnz,a,pn %xcc, fpok 706*7bafd143Sjb145095 or %g0, FPE_FLTINV, %o3 ! fp invalid code 707*7bafd143Sjb145095 708*7bafd143Sjb145095cexec_err: 709*7bafd143Sjb145095 set .badfpcexcmsg, %o0 ! panic message 710*7bafd143Sjb145095 call panic ! panic if no cexc bit set 711*7bafd143Sjb145095 mov %g1, %o1 712*7bafd143Sjb145095fpok: 713*7bafd143Sjb145095 mov %l1, %o0 ! saved *rp 714*7bafd143Sjb145095 call fpu_trap ! fpu_trap(®s, addr, type, code) 715*7bafd143Sjb145095 ldn [%o0 + PC_OFF], %o1 ! address of trapping instruction 716*7bafd143Sjb145095 717*7bafd143Sjb145095 rd %fprs, %g1 ! read fprs, save value in %g1 718*7bafd143Sjb145095 st %g1, [%l3 + FPU_FPRS] ! save fprs 719*7bafd143Sjb145095 jmp %l0 + 8 ! jump to saved return address 720*7bafd143Sjb145095 stx %fsr, [%l3 + FPU_FSR] ! save fsr 721*7bafd143Sjb145095 SET_SIZE(_fp_ieee_exception) 722*7bafd143Sjb145095 723*7bafd143Sjb145095.badfpcexcmsg: 724*7bafd143Sjb145095 .asciz "No floating point exception, fsr %llx" 725*7bafd143Sjb145095 726*7bafd143Sjb145095#endif /* lint */ 727