unsigned int EmulateCPRT(const unsigned int opcode) { if (opcode & 0x800000) { /* This is some variant of a comparison (PerformComparison will sort out which one). Since most of the other CPRT instructions are oddball cases of some sort or other it makes sense to pull this out into a fast path. */ return PerformComparison(opcode); } /* Hint to GCC that we'd like a jump table rather than a load of CMPs */ switch ((opcode & 0x700000) >> 20) { case FLT_CODE >> 20: return PerformFLT(opcode); break; case FIX_CODE >> 20: return PerformFIX(opcode); break; case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break; case RFS_CODE >> 20: writeRegister(getRd(opcode), readFPSR()); break; default: return 0; } return 1; }
unsigned int PerformFIX(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); unsigned int Fn = getFm(opcode); SetRoundingMode(opcode); switch (fpa11->fType[Fn]) { case typeSingle: { writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle)); } break; case typeDouble: { writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble)); } break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: { writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); } break; #endif default: return 0; } return 1; }
unsigned int PerformFLT(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); struct roundingData roundData; roundData.mode = SetRoundingMode(opcode); roundData.precision = SetRoundingPrecision(opcode); roundData.exception = 0; switch (opcode & MASK_ROUNDING_PRECISION) { case ROUND_SINGLE: { fpa11->fType[getFn(opcode)] = typeSingle; fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode))); } break; case ROUND_DOUBLE: { fpa11->fType[getFn(opcode)] = typeDouble; fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode))); } break; #ifdef CONFIG_FPE_NWFPE_XP case ROUND_EXTENDED: { fpa11->fType[getFn(opcode)] = typeExtended; fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode))); } break; #endif default: return 0; } if (roundData.exception) float_raise(roundData.exception); return 1; }
unsigned int PerformFIX(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); unsigned int Fn = getFm(opcode); struct roundingData roundData; roundData.mode = SetRoundingMode(opcode); roundData.precision = SetRoundingPrecision(opcode); roundData.exception = 0; switch (fpa11->fType[Fn]) { case typeSingle: { writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle)); } break; case typeDouble: { writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble)); } break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: { writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended)); } break; #endif default: return 0; } if (roundData.exception) float_raise(roundData.exception); return 1; }