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, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "fpa11.h" 22 #include "fpu/softfloat.h" 23 #include "fpopcode.h" 24 25 float64 float64_exp(float64 Fm); 26 float64 float64_ln(float64 Fm); 27 float64 float64_sin(float64 rFm); 28 float64 float64_cos(float64 rFm); 29 float64 float64_arcsin(float64 rFm); 30 float64 float64_arctan(float64 rFm); 31 float64 float64_log(float64 rFm); 32 float64 float64_tan(float64 rFm); 33 float64 float64_arccos(float64 rFm); 34 float64 float64_pow(float64 rFn,float64 rFm); 35 float64 float64_pol(float64 rFn,float64 rFm); 36 37 unsigned int DoubleCPDO(const unsigned int opcode) 38 { 39 FPA11 *fpa11 = GET_FPA11(); 40 float64 rFm, rFn = float64_zero; 41 unsigned int Fd, Fm, Fn, nRc = 1; 42 43 //printk("DoubleCPDO(0x%08x)\n",opcode); 44 45 Fm = getFm(opcode); 46 if (CONSTANT_FM(opcode)) 47 { 48 rFm = getDoubleConstant(Fm); 49 } 50 else 51 { 52 switch (fpa11->fType[Fm]) 53 { 54 case typeSingle: 55 rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status); 56 break; 57 58 case typeDouble: 59 rFm = fpa11->fpreg[Fm].fDouble; 60 break; 61 62 case typeExtended: 63 // !! patb 64 //printk("not implemented! why not?\n"); 65 //!! ScottB 66 // should never get here, if extended involved 67 // then other operand should be promoted then 68 // ExtendedCPDO called. 69 break; 70 71 default: return 0; 72 } 73 } 74 75 if (!MONADIC_INSTRUCTION(opcode)) 76 { 77 Fn = getFn(opcode); 78 switch (fpa11->fType[Fn]) 79 { 80 case typeSingle: 81 rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status); 82 break; 83 84 case typeDouble: 85 rFn = fpa11->fpreg[Fn].fDouble; 86 break; 87 88 default: return 0; 89 } 90 } 91 92 Fd = getFd(opcode); 93 /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */ 94 switch (opcode & MASK_ARITHMETIC_OPCODE) 95 { 96 /* dyadic opcodes */ 97 case ADF_CODE: 98 fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm, &fpa11->fp_status); 99 break; 100 101 case MUF_CODE: 102 case FML_CODE: 103 fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm, &fpa11->fp_status); 104 break; 105 106 case SUF_CODE: 107 fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm, &fpa11->fp_status); 108 break; 109 110 case RSF_CODE: 111 fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn, &fpa11->fp_status); 112 break; 113 114 case DVF_CODE: 115 case FDV_CODE: 116 fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm, &fpa11->fp_status); 117 break; 118 119 case RDF_CODE: 120 case FRD_CODE: 121 fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn, &fpa11->fp_status); 122 break; 123 124 #if 0 125 case POW_CODE: 126 fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm); 127 break; 128 129 case RPW_CODE: 130 fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn); 131 break; 132 #endif 133 134 case RMF_CODE: 135 fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm, &fpa11->fp_status); 136 break; 137 138 #if 0 139 case POL_CODE: 140 fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm); 141 break; 142 #endif 143 144 /* monadic opcodes */ 145 case MVF_CODE: 146 fpa11->fpreg[Fd].fDouble = rFm; 147 break; 148 149 case MNF_CODE: 150 { 151 unsigned int *p = (unsigned int*)&rFm; 152 #ifdef HOST_WORDS_BIGENDIAN 153 p[0] ^= 0x80000000; 154 #else 155 p[1] ^= 0x80000000; 156 #endif 157 fpa11->fpreg[Fd].fDouble = rFm; 158 } 159 break; 160 161 case ABS_CODE: 162 { 163 unsigned int *p = (unsigned int*)&rFm; 164 #ifdef HOST_WORDS_BIGENDIAN 165 p[0] &= 0x7fffffff; 166 #else 167 p[1] &= 0x7fffffff; 168 #endif 169 fpa11->fpreg[Fd].fDouble = rFm; 170 } 171 break; 172 173 case RND_CODE: 174 case URD_CODE: 175 fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm, &fpa11->fp_status); 176 break; 177 178 case SQT_CODE: 179 fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm, &fpa11->fp_status); 180 break; 181 182 #if 0 183 case LOG_CODE: 184 fpa11->fpreg[Fd].fDouble = float64_log(rFm); 185 break; 186 187 case LGN_CODE: 188 fpa11->fpreg[Fd].fDouble = float64_ln(rFm); 189 break; 190 191 case EXP_CODE: 192 fpa11->fpreg[Fd].fDouble = float64_exp(rFm); 193 break; 194 195 case SIN_CODE: 196 fpa11->fpreg[Fd].fDouble = float64_sin(rFm); 197 break; 198 199 case COS_CODE: 200 fpa11->fpreg[Fd].fDouble = float64_cos(rFm); 201 break; 202 203 case TAN_CODE: 204 fpa11->fpreg[Fd].fDouble = float64_tan(rFm); 205 break; 206 207 case ASN_CODE: 208 fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm); 209 break; 210 211 case ACS_CODE: 212 fpa11->fpreg[Fd].fDouble = float64_arccos(rFm); 213 break; 214 215 case ATN_CODE: 216 fpa11->fpreg[Fd].fDouble = float64_arctan(rFm); 217 break; 218 #endif 219 220 case NRM_CODE: 221 break; 222 223 default: 224 { 225 nRc = 0; 226 } 227 } 228 229 if (0 != nRc) fpa11->fType[Fd] = typeDouble; 230 return nRc; 231 } 232 233 #if 0 234 float64 float64_exp(float64 rFm) 235 { 236 return rFm; 237 //series 238 } 239 240 float64 float64_ln(float64 rFm) 241 { 242 return rFm; 243 //series 244 } 245 246 float64 float64_sin(float64 rFm) 247 { 248 return rFm; 249 //series 250 } 251 252 float64 float64_cos(float64 rFm) 253 { 254 return rFm; 255 //series 256 } 257 258 #if 0 259 float64 float64_arcsin(float64 rFm) 260 { 261 //series 262 } 263 264 float64 float64_arctan(float64 rFm) 265 { 266 //series 267 } 268 #endif 269 270 float64 float64_log(float64 rFm) 271 { 272 return float64_div(float64_ln(rFm),getDoubleConstant(7)); 273 } 274 275 float64 float64_tan(float64 rFm) 276 { 277 return float64_div(float64_sin(rFm),float64_cos(rFm)); 278 } 279 280 float64 float64_arccos(float64 rFm) 281 { 282 return rFm; 283 //return float64_sub(halfPi,float64_arcsin(rFm)); 284 } 285 286 float64 float64_pow(float64 rFn,float64 rFm) 287 { 288 return float64_exp(float64_mul(rFm,float64_ln(rFn))); 289 } 290 291 float64 float64_pol(float64 rFn,float64 rFm) 292 { 293 return float64_arctan(float64_div(rFn,rFm)); 294 } 295 #endif 296