0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "fpa11.h"
0012 #include "fpopcode.h"
0013 #include "fpa11.inl"
0014 #include "fpmodule.h"
0015 #include "fpmodule.inl"
0016 #include "softfloat.h"
0017
0018 unsigned int PerformFLT(const unsigned int opcode);
0019 unsigned int PerformFIX(const unsigned int opcode);
0020
0021 static unsigned int PerformComparison(const unsigned int opcode);
0022
0023 unsigned int EmulateCPRT(const unsigned int opcode)
0024 {
0025
0026 if (opcode & 0x800000) {
0027
0028
0029
0030
0031 return PerformComparison(opcode);
0032 }
0033
0034
0035 switch ((opcode & 0x700000) >> 20) {
0036 case FLT_CODE >> 20:
0037 return PerformFLT(opcode);
0038 break;
0039 case FIX_CODE >> 20:
0040 return PerformFIX(opcode);
0041 break;
0042
0043 case WFS_CODE >> 20:
0044 writeFPSR(readRegister(getRd(opcode)));
0045 break;
0046 case RFS_CODE >> 20:
0047 writeRegister(getRd(opcode), readFPSR());
0048 break;
0049
0050 default:
0051 return 0;
0052 }
0053
0054 return 1;
0055 }
0056
0057 unsigned int PerformFLT(const unsigned int opcode)
0058 {
0059 FPA11 *fpa11 = GET_FPA11();
0060 struct roundingData roundData;
0061
0062 roundData.mode = SetRoundingMode(opcode);
0063 roundData.precision = SetRoundingPrecision(opcode);
0064 roundData.exception = 0;
0065
0066 switch (opcode & MASK_ROUNDING_PRECISION) {
0067 case ROUND_SINGLE:
0068 {
0069 fpa11->fType[getFn(opcode)] = typeSingle;
0070 fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode)));
0071 }
0072 break;
0073
0074 case ROUND_DOUBLE:
0075 {
0076 fpa11->fType[getFn(opcode)] = typeDouble;
0077 fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode)));
0078 }
0079 break;
0080
0081 #ifdef CONFIG_FPE_NWFPE_XP
0082 case ROUND_EXTENDED:
0083 {
0084 fpa11->fType[getFn(opcode)] = typeExtended;
0085 fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode)));
0086 }
0087 break;
0088 #endif
0089
0090 default:
0091 return 0;
0092 }
0093
0094 if (roundData.exception)
0095 float_raise(roundData.exception);
0096
0097 return 1;
0098 }
0099
0100 unsigned int PerformFIX(const unsigned int opcode)
0101 {
0102 FPA11 *fpa11 = GET_FPA11();
0103 unsigned int Fn = getFm(opcode);
0104 struct roundingData roundData;
0105
0106 roundData.mode = SetRoundingMode(opcode);
0107 roundData.precision = SetRoundingPrecision(opcode);
0108 roundData.exception = 0;
0109
0110 switch (fpa11->fType[Fn]) {
0111 case typeSingle:
0112 {
0113 writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));
0114 }
0115 break;
0116
0117 case typeDouble:
0118 {
0119 writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));
0120 }
0121 break;
0122
0123 #ifdef CONFIG_FPE_NWFPE_XP
0124 case typeExtended:
0125 {
0126 writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));
0127 }
0128 break;
0129 #endif
0130
0131 default:
0132 return 0;
0133 }
0134
0135 if (roundData.exception)
0136 float_raise(roundData.exception);
0137
0138 return 1;
0139 }
0140
0141
0142 static unsigned int PerformComparison(const unsigned int opcode)
0143 {
0144 FPA11 *fpa11 = GET_FPA11();
0145 unsigned int Fn = getFn(opcode), Fm = getFm(opcode);
0146 int e_flag = opcode & 0x400000;
0147 int n_flag = opcode & 0x200000;
0148 unsigned int flags = 0;
0149
0150 #ifdef CONFIG_FPE_NWFPE_XP
0151 floatx80 rFn, rFm;
0152
0153
0154
0155
0156
0157
0158 switch (fpa11->fType[Fn]) {
0159 case typeSingle:
0160
0161 if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
0162 goto unordered;
0163 rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
0164 break;
0165
0166 case typeDouble:
0167
0168 if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
0169 goto unordered;
0170 rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
0171 break;
0172
0173 case typeExtended:
0174
0175 if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
0176 goto unordered;
0177 rFn = fpa11->fpreg[Fn].fExtended;
0178 break;
0179
0180 default:
0181 return 0;
0182 }
0183
0184 if (CONSTANT_FM(opcode)) {
0185
0186 rFm = getExtendedConstant(Fm);
0187 if (floatx80_is_nan(rFm))
0188 goto unordered;
0189 } else {
0190
0191 switch (fpa11->fType[Fm]) {
0192 case typeSingle:
0193
0194 if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
0195 goto unordered;
0196 rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
0197 break;
0198
0199 case typeDouble:
0200
0201 if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
0202 goto unordered;
0203 rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
0204 break;
0205
0206 case typeExtended:
0207
0208 if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
0209 goto unordered;
0210 rFm = fpa11->fpreg[Fm].fExtended;
0211 break;
0212
0213 default:
0214 return 0;
0215 }
0216 }
0217
0218 if (n_flag)
0219 rFm.high ^= 0x8000;
0220
0221
0222 if (floatx80_lt(rFn, rFm))
0223 flags |= CC_NEGATIVE;
0224
0225
0226 if (floatx80_eq(rFn, rFm))
0227 flags |= CC_ZERO;
0228
0229
0230 if (floatx80_lt(rFm, rFn))
0231 flags |= CC_CARRY;
0232
0233 #else
0234 if (CONSTANT_FM(opcode)) {
0235
0236
0237 if (fpa11->fType[Fn] == typeSingle) {
0238 float32 rFm = getSingleConstant(Fm);
0239 float32 rFn = fpa11->fpreg[Fn].fSingle;
0240
0241 if (float32_is_nan(rFn))
0242 goto unordered;
0243
0244 if (n_flag)
0245 rFm ^= 0x80000000;
0246
0247
0248 if (float32_lt_nocheck(rFn, rFm))
0249 flags |= CC_NEGATIVE;
0250
0251
0252 if (float32_eq_nocheck(rFn, rFm))
0253 flags |= CC_ZERO;
0254
0255
0256 if (float32_lt_nocheck(rFm, rFn))
0257 flags |= CC_CARRY;
0258 } else {
0259 float64 rFm = getDoubleConstant(Fm);
0260 float64 rFn = fpa11->fpreg[Fn].fDouble;
0261
0262 if (float64_is_nan(rFn))
0263 goto unordered;
0264
0265 if (n_flag)
0266 rFm ^= 0x8000000000000000ULL;
0267
0268
0269 if (float64_lt_nocheck(rFn, rFm))
0270 flags |= CC_NEGATIVE;
0271
0272
0273 if (float64_eq_nocheck(rFn, rFm))
0274 flags |= CC_ZERO;
0275
0276
0277 if (float64_lt_nocheck(rFm, rFn))
0278 flags |= CC_CARRY;
0279 }
0280 } else {
0281
0282 if (fpa11->fType[Fn] == typeSingle
0283 && fpa11->fType[Fm] == typeSingle) {
0284 float32 rFm = fpa11->fpreg[Fm].fSingle;
0285 float32 rFn = fpa11->fpreg[Fn].fSingle;
0286
0287 if (float32_is_nan(rFn)
0288 || float32_is_nan(rFm))
0289 goto unordered;
0290
0291 if (n_flag)
0292 rFm ^= 0x80000000;
0293
0294
0295 if (float32_lt_nocheck(rFn, rFm))
0296 flags |= CC_NEGATIVE;
0297
0298
0299 if (float32_eq_nocheck(rFn, rFm))
0300 flags |= CC_ZERO;
0301
0302
0303 if (float32_lt_nocheck(rFm, rFn))
0304 flags |= CC_CARRY;
0305 } else {
0306
0307 float64 rFm, rFn;
0308
0309 rFm = (fpa11->fType[Fm] == typeSingle) ?
0310 float32_to_float64(fpa11->fpreg[Fm].fSingle)
0311 : fpa11->fpreg[Fm].fDouble;
0312
0313 rFn = (fpa11->fType[Fn] == typeSingle) ?
0314 float32_to_float64(fpa11->fpreg[Fn].fSingle)
0315 : fpa11->fpreg[Fn].fDouble;
0316
0317 if (float64_is_nan(rFn)
0318 || float64_is_nan(rFm))
0319 goto unordered;
0320
0321 if (n_flag)
0322 rFm ^= 0x8000000000000000ULL;
0323
0324
0325 if (float64_lt_nocheck(rFn, rFm))
0326 flags |= CC_NEGATIVE;
0327
0328
0329 if (float64_eq_nocheck(rFn, rFm))
0330 flags |= CC_ZERO;
0331
0332
0333 if (float64_lt_nocheck(rFm, rFn))
0334 flags |= CC_CARRY;
0335 }
0336 }
0337
0338 #endif
0339
0340 writeConditionCodes(flags);
0341
0342 return 1;
0343
0344 unordered:
0345
0346
0347
0348
0349
0350 flags |= CC_OVERFLOW;
0351 flags &= ~(CC_ZERO | CC_NEGATIVE);
0352
0353 if (BIT_AC & readFPSR())
0354 flags |= CC_CARRY;
0355
0356 if (e_flag)
0357 float_raise(float_flag_invalid);
0358
0359 writeConditionCodes(flags);
0360 return 1;
0361 }