Piotr Caban : msvcrt: Support fdiv m64fp in i386 _fpieee_flt.

Alexandre Julliard julliard at winehq.org
Mon Dec 19 13:10:38 CST 2016


Module: wine
Branch: stable
Commit: 4690483f6bb74a98cb2d5909a29da462ace7abbe
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4690483f6bb74a98cb2d5909a29da462ace7abbe

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Aug 24 13:58:00 2016 +0200

msvcrt: Support fdiv m64fp in i386 _fpieee_flt.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit a6ffb1d2cf4b86290e61e1c44c8e3c9179c4172d)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 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 2103c1a..79d5a76 100644
--- a/dlls/msvcrt/except_i386.c
+++ b/dlls/msvcrt/except_i386.c
@@ -1137,8 +1137,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 3ddd835..8dc2929 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -1148,6 +1148,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,
     _FpFormatFp80,




More information about the wine-cvs mailing list