1/* 2 * This file is part of SIS. 3 * 4 * SIS, SPARC instruction simulator. Copyright (C) 1995 Jiri Gaisler, European 5 * Space Agency 6 * 7 * This program is free software; you can redistribute it and/or modify it under 8 * the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along with 18 * this program; if not, write to the Free Software Foundation, Inc., 675 19 * Mass Ave, Cambridge, MA 02139, USA. 20 * 21 * 22 * This file implements the interface between the host and the simulated 23 * FPU. IEEE trap handling is done as follows: 24 * 1. In the host, all IEEE traps are masked 25 * 2. After each simulated FPU instruction, check if any exception occured 26 * by reading the exception bits from the host FPU status register 27 * (get_accex()). 28 * 3. Propagate any exceptions to the simulated FSR. 29 * 4. Clear host exception bits 30 * 31 * 32 * This can also be done using ieee_flags() library routine on sun. 33 */ 34 35#include "sis.h" 36 37/* Forward declarations */ 38 39extern uint32 _get_sw PARAMS ((void)); 40extern uint32 _get_cw PARAMS ((void)); 41static void __setfpucw PARAMS ((unsigned short fpu_control)); 42 43/* This host dependent routine should return the accrued exceptions */ 44int 45get_accex() 46{ 47#ifdef sparc 48 return ((_get_fsr_raw() >> 5) & 0x1F); 49#elif i386 50 uint32 accx; 51 52 accx = _get_sw() & 0x3f; 53 accx = ((accx & 1) << 4) | ((accx & 2) >> 1) | ((accx & 4) >> 1) | 54 (accx & 8) | ((accx & 16) >> 2) | ((accx & 32) >> 5); 55 return(accx); 56#else 57 return(0); 58#warning no fpu trap support for this target 59#endif 60 61} 62 63/* How to clear the accrued exceptions */ 64void 65clear_accex() 66{ 67#ifdef sparc 68 set_fsr((_get_fsr_raw() & ~0x3e0)); 69#elif i386 70 asm("\n" 71".text\n" 72" fnclex\n" 73"\n" 74" "); 75#else 76#warning no fpu trap support for this target 77#endif 78} 79 80/* How to map SPARC FSR onto the host */ 81void 82set_fsr(fsr) 83uint32 fsr; 84{ 85#ifdef sparc 86 _set_fsr_raw(fsr & ~0x0f800000); 87#elif i386 88 void __setfpucw(unsigned short fpu_control); 89 uint32 rawfsr; 90 91 fsr >>= 30; 92 switch (fsr) { 93 case 0: 94 case 2: break; 95 case 1: fsr = 3; 96 case 3: fsr = 1; 97 } 98 rawfsr = _get_cw(); 99 rawfsr |= (fsr << 10) | 0x3ff; 100 __setfpucw(rawfsr); 101#else 102#warning no fpu trap support for this target 103#endif 104} 105 106 107/* Host dependent support functions */ 108 109#ifdef sparc 110 111 asm("\n" 112"\n" 113".text\n" 114" .align 4\n" 115" .global __set_fsr_raw,_set_fsr_raw\n" 116"__set_fsr_raw:\n" 117"_set_fsr_raw:\n" 118" save %sp,-104,%sp\n" 119" st %i0,[%fp+68]\n" 120" ld [%fp+68], %fsr\n" 121" mov 0,%i0\n" 122" ret\n" 123" restore\n" 124"\n" 125" .align 4\n" 126" .global __get_fsr_raw\n" 127" .global _get_fsr_raw\n" 128"__get_fsr_raw:\n" 129"_get_fsr_raw:\n" 130" save %sp,-104,%sp\n" 131" st %fsr,[%fp+68]\n" 132" ld [%fp+68], %i0\n" 133" ret\n" 134" restore\n" 135"\n" 136" "); 137 138#elif i386 139 140 asm("\n" 141"\n" 142".text\n" 143" .align 8\n" 144".globl _get_sw,__get_sw\n" 145"__get_sw:\n" 146"_get_sw:\n" 147" pushl %ebp\n" 148" movl %esp,%ebp\n" 149" movl $0,%eax\n" 150" fnstsw %ax\n" 151" movl %ebp,%esp\n" 152" popl %ebp\n" 153" ret\n" 154"\n" 155" .align 8\n" 156".globl _get_cw,__get_cw\n" 157"__get_cw:\n" 158"_get_cw:\n" 159" pushl %ebp\n" 160" movl %esp,%ebp\n" 161" subw $2,%esp\n" 162" fnstcw -2(%ebp)\n" 163" movw -2(%ebp),%eax\n" 164" movl %ebp,%esp\n" 165" popl %ebp\n" 166" ret\n" 167"\n" 168"\n" 169" "); 170 171 172#else 173#warning no fpu trap support for this target 174#endif 175 176#if i386 177/* #if defined _WIN32 || defined __GO32__ */ 178/* This is so floating exception handling works on NT 179 These definitions are from the linux fpu_control.h, which 180 doesn't exist on NT. 181 182 default to: 183 - extended precision 184 - rounding to nearest 185 - exceptions on overflow, zero divide and NaN 186*/ 187#define _FPU_DEFAULT 0x1372 188#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ 189 190static void 191__setfpucw(unsigned short fpu_control) 192{ 193 volatile unsigned short cw; 194 195 /* If user supplied _fpu_control, use it ! */ 196 if (!fpu_control) 197 { 198 /* use defaults */ 199 fpu_control = _FPU_DEFAULT; 200 } 201 /* Get Control Word */ 202 __asm__ volatile ("fnstcw %0" : "=m" (cw) : ); 203 204 /* mask in */ 205 cw &= _FPU_RESERVED; 206 cw = cw | (fpu_control & ~_FPU_RESERVED); 207 208 /* set cw */ 209 __asm__ volatile ("fldcw %0" :: "m" (cw)); 210} 211/* #endif */ 212#endif 213