1 /* 2 NetWinder Floating Point Emulator 3 (c) Rebel.COM, 1998,1999 4 5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org> 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #include "fpa11.h" 23 #include "softfloat.h" 24 #include "fpopcode.h" 25 26 float64 float64_exp(float64 Fm); 27 float64 float64_ln(float64 Fm); 28 float64 float64_sin(float64 rFm); 29 float64 float64_cos(float64 rFm); 30 float64 float64_arcsin(float64 rFm); 31 float64 float64_arctan(float64 rFm); 32 float64 float64_log(float64 rFm); 33 float64 float64_tan(float64 rFm); 34 float64 float64_arccos(float64 rFm); 35 float64 float64_pow(float64 rFn,float64 rFm); 36 float64 float64_pol(float64 rFn,float64 rFm); 37 38 unsigned int DoubleCPDO(const unsigned int opcode) 39 { 40 FPA11 *fpa11 = GET_FPA11(); 41 float64 rFm, rFn = 0; 42 unsigned int Fd, Fm, Fn, nRc = 1; 43 44 //printk("DoubleCPDO(0x%08x)\n",opcode); 45 46 Fm = getFm(opcode); 47 if (CONSTANT_FM(opcode)) 48 { 49 rFm = getDoubleConstant(Fm); 50 } 51 else 52 { 53 switch (fpa11->fType[Fm]) 54 { 55 case typeSingle: 56 rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); 57 break; 58 59 case typeDouble: 60 rFm = fpa11->fpreg[Fm].fDouble; 61 break; 62 63 case typeExtended: 64 // !! patb 65 //printk("not implemented! why not?\n"); 66 //!! ScottB 67 // should never get here, if extended involved 68 // then other operand should be promoted then 69 // ExtendedCPDO called. 70 break; 71 72 default: return 0; 73 } 74 } 75 76 if (!MONADIC_INSTRUCTION(opcode)) 77 { 78 Fn = getFn(opcode); 79 switch (fpa11->fType[Fn]) 80 { 81 case typeSingle: 82 rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); 83 break; 84 85 case typeDouble: 86 rFn = fpa11->fpreg[Fn].fDouble; 87 break; 88 89 default: return 0; 90 } 91 } 92 93 Fd = getFd(opcode); 94 /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */ 95 switch (opcode & MASK_ARITHMETIC_OPCODE) 96 { 97 /* dyadic opcodes */ 98 case ADF_CODE: 99 fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm); 100 break; 101 102 case MUF_CODE: 103 case FML_CODE: 104 fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm); 105 break; 106 107 case SUF_CODE: 108 fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm); 109 break; 110 111 case RSF_CODE: 112 fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn); 113 break; 114 115 case DVF_CODE: 116 case FDV_CODE: 117 fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm); 118 break; 119 120 case RDF_CODE: 121 case FRD_CODE: 122 fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn); 123 break; 124 125 #if 0 126 case POW_CODE: 127 fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm); 128 break; 129 130 case RPW_CODE: 131 fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn); 132 break; 133 #endif 134 135 case RMF_CODE: 136 fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm); 137 break; 138 139 #if 0 140 case POL_CODE: 141 fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm); 142 break; 143 #endif 144 145 /* monadic opcodes */ 146 case MVF_CODE: 147 fpa11->fpreg[Fd].fDouble = rFm; 148 break; 149 150 case MNF_CODE: 151 { 152 unsigned int *p = (unsigned int*)&rFm; 153 p[1] ^= 0x80000000; 154 fpa11->fpreg[Fd].fDouble = rFm; 155 } 156 break; 157 158 case ABS_CODE: 159 { 160 unsigned int *p = (unsigned int*)&rFm; 161 p[1] &= 0x7fffffff; 162 fpa11->fpreg[Fd].fDouble = rFm; 163 } 164 break; 165 166 case RND_CODE: 167 case URD_CODE: 168 fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm); 169 break; 170 171 case SQT_CODE: 172 fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm); 173 break; 174 175 #if 0 176 case LOG_CODE: 177 fpa11->fpreg[Fd].fDouble = float64_log(rFm); 178 break; 179 180 case LGN_CODE: 181 fpa11->fpreg[Fd].fDouble = float64_ln(rFm); 182 break; 183 184 case EXP_CODE: 185 fpa11->fpreg[Fd].fDouble = float64_exp(rFm); 186 break; 187 188 case SIN_CODE: 189 fpa11->fpreg[Fd].fDouble = float64_sin(rFm); 190 break; 191 192 case COS_CODE: 193 fpa11->fpreg[Fd].fDouble = float64_cos(rFm); 194 break; 195 196 case TAN_CODE: 197 fpa11->fpreg[Fd].fDouble = float64_tan(rFm); 198 break; 199 200 case ASN_CODE: 201 fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm); 202 break; 203 204 case ACS_CODE: 205 fpa11->fpreg[Fd].fDouble = float64_arccos(rFm); 206 break; 207 208 case ATN_CODE: 209 fpa11->fpreg[Fd].fDouble = float64_arctan(rFm); 210 break; 211 #endif 212 213 case NRM_CODE: 214 break; 215 216 default: 217 { 218 nRc = 0; 219 } 220 } 221 222 if (0 != nRc) fpa11->fType[Fd] = typeDouble; 223 return nRc; 224 } 225 226 #if 0 227 float64 float64_exp(float64 rFm) 228 { 229 return rFm; 230 //series 231 } 232 233 float64 float64_ln(float64 rFm) 234 { 235 return rFm; 236 //series 237 } 238 239 float64 float64_sin(float64 rFm) 240 { 241 return rFm; 242 //series 243 } 244 245 float64 float64_cos(float64 rFm) 246 { 247 return rFm; 248 //series 249 } 250 251 #if 0 252 float64 float64_arcsin(float64 rFm) 253 { 254 //series 255 } 256 257 float64 float64_arctan(float64 rFm) 258 { 259 //series 260 } 261 #endif 262 263 float64 float64_log(float64 rFm) 264 { 265 return float64_div(float64_ln(rFm),getDoubleConstant(7)); 266 } 267 268 float64 float64_tan(float64 rFm) 269 { 270 return float64_div(float64_sin(rFm),float64_cos(rFm)); 271 } 272 273 float64 float64_arccos(float64 rFm) 274 { 275 return rFm; 276 //return float64_sub(halfPi,float64_arcsin(rFm)); 277 } 278 279 float64 float64_pow(float64 rFn,float64 rFm) 280 { 281 return float64_exp(float64_mul(rFm,float64_ln(rFn))); 282 } 283 284 float64 float64_pol(float64 rFn,float64 rFm) 285 { 286 return float64_arctan(float64_div(rFn,rFm)); 287 } 288 #endif 289