1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 NetWinder Floating Point Emulator 4 (c) Rebel.COM, 1998,1999 5 6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org> 7 8 */ 9 10 #include "fpa11.h" 11 #include "softfloat.h" 12 #include "fpopcode.h" 13 14 floatx80 floatx80_exp(floatx80 Fm); 15 floatx80 floatx80_ln(floatx80 Fm); 16 floatx80 floatx80_sin(floatx80 rFm); 17 floatx80 floatx80_cos(floatx80 rFm); 18 floatx80 floatx80_arcsin(floatx80 rFm); 19 floatx80 floatx80_arctan(floatx80 rFm); 20 floatx80 floatx80_log(floatx80 rFm); 21 floatx80 floatx80_tan(floatx80 rFm); 22 floatx80 floatx80_arccos(floatx80 rFm); 23 floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); 24 floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); 25 26 static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) 27 { 28 return floatx80_sub(roundData, rFm, rFn); 29 } 30 31 static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) 32 { 33 return floatx80_div(roundData, rFm, rFn); 34 } 35 36 static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = { 37 [ADF_CODE >> 20] = floatx80_add, 38 [MUF_CODE >> 20] = floatx80_mul, 39 [SUF_CODE >> 20] = floatx80_sub, 40 [RSF_CODE >> 20] = floatx80_rsf, 41 [DVF_CODE >> 20] = floatx80_div, 42 [RDF_CODE >> 20] = floatx80_rdv, 43 [RMF_CODE >> 20] = floatx80_rem, 44 45 /* strictly, these opcodes should not be implemented */ 46 [FML_CODE >> 20] = floatx80_mul, 47 [FDV_CODE >> 20] = floatx80_div, 48 [FRD_CODE >> 20] = floatx80_rdv, 49 }; 50 51 static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm) 52 { 53 return rFm; 54 } 55 56 static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm) 57 { 58 rFm.high ^= 0x8000; 59 return rFm; 60 } 61 62 static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm) 63 { 64 rFm.high &= 0x7fff; 65 return rFm; 66 } 67 68 static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = { 69 [MVF_CODE >> 20] = floatx80_mvf, 70 [MNF_CODE >> 20] = floatx80_mnf, 71 [ABS_CODE >> 20] = floatx80_abs, 72 [RND_CODE >> 20] = floatx80_round_to_int, 73 [URD_CODE >> 20] = floatx80_round_to_int, 74 [SQT_CODE >> 20] = floatx80_sqrt, 75 [NRM_CODE >> 20] = floatx80_mvf, 76 }; 77 78 unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) 79 { 80 FPA11 *fpa11 = GET_FPA11(); 81 floatx80 rFm; 82 unsigned int Fm, opc_mask_shift; 83 84 Fm = getFm(opcode); 85 if (CONSTANT_FM(opcode)) { 86 rFm = getExtendedConstant(Fm); 87 } else { 88 switch (fpa11->fType[Fm]) { 89 case typeSingle: 90 rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); 91 break; 92 93 case typeDouble: 94 rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); 95 break; 96 97 case typeExtended: 98 rFm = fpa11->fpreg[Fm].fExtended; 99 break; 100 101 default: 102 return 0; 103 } 104 } 105 106 opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; 107 if (!MONADIC_INSTRUCTION(opcode)) { 108 unsigned int Fn = getFn(opcode); 109 floatx80 rFn; 110 111 switch (fpa11->fType[Fn]) { 112 case typeSingle: 113 rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); 114 break; 115 116 case typeDouble: 117 rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); 118 break; 119 120 case typeExtended: 121 rFn = fpa11->fpreg[Fn].fExtended; 122 break; 123 124 default: 125 return 0; 126 } 127 128 if (dyadic_extended[opc_mask_shift]) { 129 rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm); 130 } else { 131 return 0; 132 } 133 } else { 134 if (monadic_extended[opc_mask_shift]) { 135 rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm); 136 } else { 137 return 0; 138 } 139 } 140 141 return 1; 142 } 143