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 "qemu/osdep.h" 22 #include "fpa11.h" 23 #include "fpu/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 = float64_zero; 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, &fpa11->fp_status); 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, &fpa11->fp_status); 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, &fpa11->fp_status); 100 break; 101 102 case MUF_CODE: 103 case FML_CODE: 104 fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm, &fpa11->fp_status); 105 break; 106 107 case SUF_CODE: 108 fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm, &fpa11->fp_status); 109 break; 110 111 case RSF_CODE: 112 fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn, &fpa11->fp_status); 113 break; 114 115 case DVF_CODE: 116 case FDV_CODE: 117 fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm, &fpa11->fp_status); 118 break; 119 120 case RDF_CODE: 121 case FRD_CODE: 122 fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn, &fpa11->fp_status); 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, &fpa11->fp_status); 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 #ifdef HOST_WORDS_BIGENDIAN 154 p[0] ^= 0x80000000; 155 #else 156 p[1] ^= 0x80000000; 157 #endif 158 fpa11->fpreg[Fd].fDouble = rFm; 159 } 160 break; 161 162 case ABS_CODE: 163 { 164 unsigned int *p = (unsigned int*)&rFm; 165 #ifdef HOST_WORDS_BIGENDIAN 166 p[0] &= 0x7fffffff; 167 #else 168 p[1] &= 0x7fffffff; 169 #endif 170 fpa11->fpreg[Fd].fDouble = rFm; 171 } 172 break; 173 174 case RND_CODE: 175 case URD_CODE: 176 fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm, &fpa11->fp_status); 177 break; 178 179 case SQT_CODE: 180 fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm, &fpa11->fp_status); 181 break; 182 183 #if 0 184 case LOG_CODE: 185 fpa11->fpreg[Fd].fDouble = float64_log(rFm); 186 break; 187 188 case LGN_CODE: 189 fpa11->fpreg[Fd].fDouble = float64_ln(rFm); 190 break; 191 192 case EXP_CODE: 193 fpa11->fpreg[Fd].fDouble = float64_exp(rFm); 194 break; 195 196 case SIN_CODE: 197 fpa11->fpreg[Fd].fDouble = float64_sin(rFm); 198 break; 199 200 case COS_CODE: 201 fpa11->fpreg[Fd].fDouble = float64_cos(rFm); 202 break; 203 204 case TAN_CODE: 205 fpa11->fpreg[Fd].fDouble = float64_tan(rFm); 206 break; 207 208 case ASN_CODE: 209 fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm); 210 break; 211 212 case ACS_CODE: 213 fpa11->fpreg[Fd].fDouble = float64_arccos(rFm); 214 break; 215 216 case ATN_CODE: 217 fpa11->fpreg[Fd].fDouble = float64_arctan(rFm); 218 break; 219 #endif 220 221 case NRM_CODE: 222 break; 223 224 default: 225 { 226 nRc = 0; 227 } 228 } 229 230 if (0 != nRc) fpa11->fType[Fd] = typeDouble; 231 return nRc; 232 } 233 234 #if 0 235 float64 float64_exp(float64 rFm) 236 { 237 return rFm; 238 //series 239 } 240 241 float64 float64_ln(float64 rFm) 242 { 243 return rFm; 244 //series 245 } 246 247 float64 float64_sin(float64 rFm) 248 { 249 return rFm; 250 //series 251 } 252 253 float64 float64_cos(float64 rFm) 254 { 255 return rFm; 256 //series 257 } 258 259 #if 0 260 float64 float64_arcsin(float64 rFm) 261 { 262 //series 263 } 264 265 float64 float64_arctan(float64 rFm) 266 { 267 //series 268 } 269 #endif 270 271 float64 float64_log(float64 rFm) 272 { 273 return float64_div(float64_ln(rFm),getDoubleConstant(7)); 274 } 275 276 float64 float64_tan(float64 rFm) 277 { 278 return float64_div(float64_sin(rFm),float64_cos(rFm)); 279 } 280 281 float64 float64_arccos(float64 rFm) 282 { 283 return rFm; 284 //return float64_sub(halfPi,float64_arcsin(rFm)); 285 } 286 287 float64 float64_pow(float64 rFn,float64 rFm) 288 { 289 return float64_exp(float64_mul(rFm,float64_ln(rFn))); 290 } 291 292 float64 float64_pol(float64 rFn,float64 rFm) 293 { 294 return float64_arctan(float64_div(rFn,rFm)); 295 } 296 #endif 297