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 3 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, see <http://www.gnu.org/licenses/>. 19 * 20 * 21 * This file implements the interface between the host and the simulated 22 * FPU. IEEE trap handling is done as follows: 23 * 1. In the host, all IEEE traps are masked 24 * 2. After each simulated FPU instruction, check if any exception occured 25 * by reading the exception bits from the host FPU status register 26 * (get_accex()). 27 * 3. Propagate any exceptions to the simulated FSR. 28 * 4. Clear host exception bits 29 * 30 * 31 * This can also be done using ieee_flags() library routine on sun. 32 */ 33 34 #include "config.h" 35 #include "sis.h" 36 37 /* Forward declarations */ 38 39 extern uint32 _get_sw PARAMS ((void)); 40 extern uint32 _get_cw PARAMS ((void)); 41 static void __setfpucw PARAMS ((unsigned short fpu_control)); 42 43 /* This host dependent routine should return the accrued exceptions */ 44 int 45 get_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 */ 64 void 65 clear_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 */ 81 void 82 set_fsr(fsr) 83 uint32 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 190 static 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