From a6ffb1d2cf4b86290e61e1c44c8e3c9179c4172d Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Wed, 24 Aug 2016 13:58:00 +0200 Subject: [PATCH] msvcrt: Support fdiv m64fp in i386 _fpieee_flt. Signed-off-by: Piotr Caban Signed-off-by: Alexandre Julliard --- dlls/msvcrt/except_i386.c | 70 ++++++++++++++++++++++++- dlls/msvcrt/msvcrt.h | 107 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 2 deletions(-) diff --git a/dlls/msvcrt/except_i386.c b/dlls/msvcrt/except_i386.c index 6a01fa76a31..d26a864dccd 100644 --- a/dlls/msvcrt/except_i386.c +++ b/dlls/msvcrt/except_i386.c @@ -1124,8 +1124,74 @@ void __stdcall _seh_longjmp_unwind4(struct MSVCRT___JUMP_BUFFER *jmp) int __cdecl _fpieee_flt(ULONG exception_code, EXCEPTION_POINTERS *ep, int (__cdecl *handler)(_FPIEEE_RECORD*)) { - FIXME("(%x %p %p) opcode: %x\n", exception_code, ep, handler, - *(ULONG*)ep->ContextRecord->FloatSave.ErrorOffset); + FLOATING_SAVE_AREA *ctx = &ep->ContextRecord->FloatSave; + _FPIEEE_RECORD rec; + int ret; + + TRACE("(%x %p %p)\n", exception_code, ep, handler); + + switch(exception_code) { + case STATUS_FLOAT_DIVIDE_BY_ZERO: + case STATUS_FLOAT_INEXACT_RESULT: + case STATUS_FLOAT_INVALID_OPERATION: + case STATUS_FLOAT_OVERFLOW: + case STATUS_FLOAT_UNDERFLOW: + break; + default: + return EXCEPTION_CONTINUE_SEARCH; + } + + memset(&rec, 0, sizeof(rec)); + rec.RoundingMode = ctx->ControlWord >> 10; + switch((ctx->ControlWord >> 8) & 0x3) { + case 0: rec.Precision = 2; break; + case 1: rec.Precision = 3; break; + case 2: rec.Precision = 1; break; + case 3: rec.Precision = 0; break; + } + rec.Status.InvalidOperation = ctx->StatusWord & 0x1; + rec.Status.ZeroDivide = ((ctx->StatusWord & 0x4) != 0); + rec.Status.Overflow = ((ctx->StatusWord & 0x8) != 0); + rec.Status.Underflow = ((ctx->StatusWord & 0x10) != 0); + rec.Status.Inexact = ((ctx->StatusWord & 0x20) != 0); + rec.Enable.InvalidOperation = ((ctx->ControlWord & 0x1) == 0); + rec.Enable.ZeroDivide = ((ctx->ControlWord & 0x4) == 0); + rec.Enable.Overflow = ((ctx->ControlWord & 0x8) == 0); + rec.Enable.Underflow = ((ctx->ControlWord & 0x10) == 0); + rec.Enable.Inexact = ((ctx->ControlWord & 0x20) == 0); + rec.Cause.InvalidOperation = rec.Enable.InvalidOperation & rec.Status.InvalidOperation; + rec.Cause.ZeroDivide = rec.Enable.ZeroDivide & rec.Status.ZeroDivide; + rec.Cause.Overflow = rec.Enable.Overflow & rec.Status.Overflow; + rec.Cause.Underflow = rec.Enable.Underflow & rec.Status.Underflow; + rec.Cause.Inexact = rec.Enable.Inexact & rec.Status.Inexact; + + TRACE("opcode: %x\n", *(ULONG*)ep->ContextRecord->FloatSave.ErrorOffset); + + if(*(WORD*)ctx->ErrorOffset == 0x35dc) { /* fdiv m64fp */ + if(exception_code==STATUS_FLOAT_DIVIDE_BY_ZERO || exception_code==STATUS_FLOAT_INVALID_OPERATION) { + rec.Operand1.OperandValid = 1; + rec.Result.OperandValid = 0; + } else { + rec.Operand1.OperandValid = 0; + rec.Result.OperandValid = 1; + } + rec.Operand2.OperandValid = 1; + rec.Operation = _FpCodeDivide; + rec.Operand1.Format = _FpFormatFp80; + memcpy(&rec.Operand1.Value.Fp80Value, ctx->RegisterArea, sizeof(rec.Operand1.Value.Fp80Value)); + rec.Operand2.Format = _FpFormatFp64; + rec.Operand2.Value.Fp64Value = *(double*)ctx->DataOffset; + rec.Result.Format = _FpFormatFp80; + memcpy(&rec.Result.Value.Fp80Value, ctx->RegisterArea, sizeof(rec.Operand1.Value.Fp80Value)); + + ret = handler(&rec); + + if(ret == EXCEPTION_CONTINUE_EXECUTION) + memcpy(ctx->RegisterArea, &rec.Result.Value.Fp80Value, sizeof(rec.Operand1.Value.Fp80Value)); + return ret; + } + + FIXME("unsupported opcode: %x\n", *(ULONG*)ep->ContextRecord->FloatSave.ErrorOffset); return EXCEPTION_CONTINUE_SEARCH; } diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index eb6273db942..71d80c9b0f7 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -1176,6 +1176,113 @@ extern char* __cdecl __unDName(char *,const char*,int,malloc_func_t,free_func_t, #define UCRTBASE_SCANF_MASK (0x0007) +typedef enum { + _FpCodeUnspecified, + _FpCodeAdd, + _FpCodeSubtract, + _FpCodeMultiply, + _FpCodeDivide, + _FpCodeSquareRoot, + _FpCodeRemainder, + _FpCodeCompare, + _FpCodeConvert, + _FpCodeRound, + _FpCodeTruncate, + _FpCodeFloor, + _FpCodeCeil, + _FpCodeAcos, + _FpCodeAsin, + _FpCodeAtan, + _FpCodeAtan2, + _FpCodeCabs, + _FpCodeCos, + _FpCodeCosh, + _FpCodeExp, + _FpCodeFabs, + _FpCodeFmod, + _FpCodeFrexp, + _FpCodeHypot, + _FpCodeLdexp, + _FpCodeLog, + _FpCodeLog10, + _FpCodeModf, + _FpCodePow, + _FpCodeSin, + _FpCodeSinh, + _FpCodeTan, + _FpCodeTanh, + _FpCodeY0, + _FpCodeY1, + _FpCodeYn, + _FpCodeLogb, + _FpCodeNextafter, + _FpCodeNegate, + _FpCodeFmin, + _FpCodeFmax, + _FpCodeConvertTrunc, + _XMMIAddps, + _XMMIAddss, + _XMMISubps, + _XMMISubss, + _XMMIMulps, + _XMMIMulss, + _XMMIDivps, + _XMMIDivss, + _XMMISqrtps, + _XMMISqrtss, + _XMMIMaxps, + _XMMIMaxss, + _XMMIMinps, + _XMMIMinss, + _XMMICmpps, + _XMMICmpss, + _XMMIComiss, + _XMMIUComiss, + _XMMICvtpi2ps, + _XMMICvtsi2ss, + _XMMICvtps2pi, + _XMMICvtss2si, + _XMMICvttps2pi, + _XMMICvttss2si, + _XMMIAddsubps, + _XMMIHaddps, + _XMMIHsubps, + _XMMI2Addpd, + _XMMI2Addsd, + _XMMI2Subpd, + _XMMI2Subsd, + _XMMI2Mulpd, + _XMMI2Mulsd, + _XMMI2Divpd, + _XMMI2Divsd, + _XMMI2Sqrtpd, + _XMMI2Sqrtsd, + _XMMI2Maxpd, + _XMMI2Maxsd, + _XMMI2Minpd, + _XMMI2Minsd, + _XMMI2Cmppd, + _XMMI2Cmpsd, + _XMMI2Comisd, + _XMMI2UComisd, + _XMMI2Cvtpd2pi, + _XMMI2Cvtsd2si, + _XMMI2Cvttpd2pi, + _XMMI2Cvttsd2si, + _XMMI2Cvtps2pd, + _XMMI2Cvtss2sd, + _XMMI2Cvtpd2ps, + _XMMI2Cvtsd2ss, + _XMMI2Cvtdq2ps, + _XMMI2Cvttps2dq, + _XMMI2Cvtps2dq, + _XMMI2Cvttpd2dq, + _XMMI2Cvtpd2dq, + _XMMI2Addsubpd, + _XMMI2Haddpd, + _XMMI2Hsubpd, +} _FP_OPERATION_CODE; + typedef enum { _FpFormatFp32, _FpFormatFp64,