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 (void); 40 extern uint32 _get_cw (void); 41 static void __setfpucw (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: 95 break; 96 97 case 1: 98 fsr = 3; 99 break; 100 101 case 3: 102 fsr = 1; 103 break; 104 } 105 rawfsr = _get_cw(); 106 rawfsr |= (fsr << 10) | 0x3ff; 107 __setfpucw(rawfsr); 108 #else 109 #warning no fpu trap support for this target 110 #endif 111 } 112 113 114 /* Host dependent support functions */ 115 116 #ifdef sparc 117 118 asm("\n" 119 "\n" 120 ".text\n" 121 " .align 4\n" 122 " .global __set_fsr_raw,_set_fsr_raw\n" 123 "__set_fsr_raw:\n" 124 "_set_fsr_raw:\n" 125 " save %sp,-104,%sp\n" 126 " st %i0,[%fp+68]\n" 127 " ld [%fp+68], %fsr\n" 128 " mov 0,%i0\n" 129 " ret\n" 130 " restore\n" 131 "\n" 132 " .align 4\n" 133 " .global __get_fsr_raw\n" 134 " .global _get_fsr_raw\n" 135 "__get_fsr_raw:\n" 136 "_get_fsr_raw:\n" 137 " save %sp,-104,%sp\n" 138 " st %fsr,[%fp+68]\n" 139 " ld [%fp+68], %i0\n" 140 " ret\n" 141 " restore\n" 142 "\n" 143 " "); 144 145 #elif i386 146 147 asm("\n" 148 "\n" 149 ".text\n" 150 " .align 8\n" 151 ".globl _get_sw,__get_sw\n" 152 "__get_sw:\n" 153 "_get_sw:\n" 154 " pushl %ebp\n" 155 " movl %esp,%ebp\n" 156 " movl $0,%eax\n" 157 " fnstsw %ax\n" 158 " movl %ebp,%esp\n" 159 " popl %ebp\n" 160 " ret\n" 161 "\n" 162 " .align 8\n" 163 ".globl _get_cw,__get_cw\n" 164 "__get_cw:\n" 165 "_get_cw:\n" 166 " pushl %ebp\n" 167 " movl %esp,%ebp\n" 168 " subw $2,%esp\n" 169 " fnstcw -2(%ebp)\n" 170 " movw -2(%ebp),%eax\n" 171 " movl %ebp,%esp\n" 172 " popl %ebp\n" 173 " ret\n" 174 "\n" 175 "\n" 176 " "); 177 178 179 #else 180 #warning no fpu trap support for this target 181 #endif 182 183 #if i386 184 /* #if defined _WIN32 || defined __GO32__ */ 185 /* This is so floating exception handling works on NT 186 These definitions are from the linux fpu_control.h, which 187 doesn't exist on NT. 188 189 default to: 190 - extended precision 191 - rounding to nearest 192 - exceptions on overflow, zero divide and NaN 193 */ 194 #define _FPU_DEFAULT 0x1372 195 #define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ 196 197 static void 198 __setfpucw(unsigned short fpu_control) 199 { 200 volatile unsigned short cw; 201 202 /* If user supplied _fpu_control, use it ! */ 203 if (!fpu_control) 204 { 205 /* use defaults */ 206 fpu_control = _FPU_DEFAULT; 207 } 208 /* Get Control Word */ 209 __asm__ volatile ("fnstcw %0" : "=m" (cw) : ); 210 211 /* mask in */ 212 cw &= _FPU_RESERVED; 213 cw = cw | (fpu_control & ~_FPU_RESERVED); 214 215 /* set cw */ 216 __asm__ volatile ("fldcw %0" :: "m" (cw)); 217 } 218 /* #endif */ 219 #endif 220