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 floatx80 floatx80_exp(floatx80 Fm); 27 floatx80 floatx80_ln(floatx80 Fm); 28 floatx80 floatx80_sin(floatx80 rFm); 29 floatx80 floatx80_cos(floatx80 rFm); 30 floatx80 floatx80_arcsin(floatx80 rFm); 31 floatx80 floatx80_arctan(floatx80 rFm); 32 floatx80 floatx80_log(floatx80 rFm); 33 floatx80 floatx80_tan(floatx80 rFm); 34 floatx80 floatx80_arccos(floatx80 rFm); 35 floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm); 36 floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm); 37 38 unsigned int ExtendedCPDO(const unsigned int opcode) 39 { 40 FPA11 *fpa11 = GET_FPA11(); 41 floatx80 rFm, rFn; 42 unsigned int Fd, Fm, Fn, nRc = 1; 43 44 //printk("ExtendedCPDO(0x%08x)\n",opcode); 45 46 Fm = getFm(opcode); 47 if (CONSTANT_FM(opcode)) 48 { 49 rFm = getExtendedConstant(Fm); 50 } 51 else 52 { 53 switch (fpa11->fType[Fm]) 54 { 55 case typeSingle: 56 rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status); 57 break; 58 59 case typeDouble: 60 rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status); 61 break; 62 63 case typeExtended: 64 rFm = fpa11->fpreg[Fm].fExtended; 65 break; 66 67 default: return 0; 68 } 69 } 70 71 if (!MONADIC_INSTRUCTION(opcode)) 72 { 73 Fn = getFn(opcode); 74 switch (fpa11->fType[Fn]) 75 { 76 case typeSingle: 77 rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status); 78 break; 79 80 case typeDouble: 81 rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status); 82 break; 83 84 case typeExtended: 85 rFn = fpa11->fpreg[Fn].fExtended; 86 break; 87 88 default: return 0; 89 } 90 } 91 92 Fd = getFd(opcode); 93 switch (opcode & MASK_ARITHMETIC_OPCODE) 94 { 95 /* dyadic opcodes */ 96 case ADF_CODE: 97 fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm, &fpa11->fp_status); 98 break; 99 100 case MUF_CODE: 101 case FML_CODE: 102 fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm, &fpa11->fp_status); 103 break; 104 105 case SUF_CODE: 106 fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm, &fpa11->fp_status); 107 break; 108 109 case RSF_CODE: 110 fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn, &fpa11->fp_status); 111 break; 112 113 case DVF_CODE: 114 case FDV_CODE: 115 fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm, &fpa11->fp_status); 116 break; 117 118 case RDF_CODE: 119 case FRD_CODE: 120 fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn, &fpa11->fp_status); 121 break; 122 123 #if 0 124 case POW_CODE: 125 fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm); 126 break; 127 128 case RPW_CODE: 129 fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn); 130 break; 131 #endif 132 133 case RMF_CODE: 134 fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm, &fpa11->fp_status); 135 break; 136 137 #if 0 138 case POL_CODE: 139 fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm); 140 break; 141 #endif 142 143 /* monadic opcodes */ 144 case MVF_CODE: 145 fpa11->fpreg[Fd].fExtended = rFm; 146 break; 147 148 case MNF_CODE: 149 rFm.high ^= 0x8000; 150 fpa11->fpreg[Fd].fExtended = rFm; 151 break; 152 153 case ABS_CODE: 154 rFm.high &= 0x7fff; 155 fpa11->fpreg[Fd].fExtended = rFm; 156 break; 157 158 case RND_CODE: 159 case URD_CODE: 160 fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm, &fpa11->fp_status); 161 break; 162 163 case SQT_CODE: 164 fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm, &fpa11->fp_status); 165 break; 166 167 #if 0 168 case LOG_CODE: 169 fpa11->fpreg[Fd].fExtended = floatx80_log(rFm); 170 break; 171 172 case LGN_CODE: 173 fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm); 174 break; 175 176 case EXP_CODE: 177 fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm); 178 break; 179 180 case SIN_CODE: 181 fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm); 182 break; 183 184 case COS_CODE: 185 fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm); 186 break; 187 188 case TAN_CODE: 189 fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm); 190 break; 191 192 case ASN_CODE: 193 fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm); 194 break; 195 196 case ACS_CODE: 197 fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm); 198 break; 199 200 case ATN_CODE: 201 fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm); 202 break; 203 #endif 204 205 case NRM_CODE: 206 break; 207 208 default: 209 { 210 nRc = 0; 211 } 212 } 213 214 if (0 != nRc) fpa11->fType[Fd] = typeExtended; 215 return nRc; 216 } 217 218 #if 0 219 floatx80 floatx80_exp(floatx80 Fm) 220 { 221 //series 222 } 223 224 floatx80 floatx80_ln(floatx80 Fm) 225 { 226 //series 227 } 228 229 floatx80 floatx80_sin(floatx80 rFm) 230 { 231 //series 232 } 233 234 floatx80 floatx80_cos(floatx80 rFm) 235 { 236 //series 237 } 238 239 floatx80 floatx80_arcsin(floatx80 rFm) 240 { 241 //series 242 } 243 244 floatx80 floatx80_arctan(floatx80 rFm) 245 { 246 //series 247 } 248 249 floatx80 floatx80_log(floatx80 rFm) 250 { 251 return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7)); 252 } 253 254 floatx80 floatx80_tan(floatx80 rFm) 255 { 256 return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm)); 257 } 258 259 floatx80 floatx80_arccos(floatx80 rFm) 260 { 261 //return floatx80_sub(halfPi,floatx80_arcsin(rFm)); 262 } 263 264 floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm) 265 { 266 return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn))); 267 } 268 269 floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm) 270 { 271 return floatx80_arctan(floatx80_div(rFn,rFm)); 272 } 273 #endif 274