mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
14 KiB
342 lines
14 KiB
//
|
|
// Alpha AXP High-performance math library exception handler.
|
|
//
|
|
// This code maps the standard DPML exception record to calls to
|
|
// the appropriate NT libc private exception handlers.
|
|
//
|
|
|
|
#include <stdarg.h>
|
|
#include <errno.h>
|
|
#include <windows.h>
|
|
#include <math.h>
|
|
#include <fpieee.h>
|
|
|
|
#pragma function(acos, asin, atan, atan2, cos, cosh, exp, fabs, fmod, log, \
|
|
log10, pow, sin, sinh, sqrt, tan, tanh)
|
|
|
|
typedef struct {
|
|
unsigned int func:6,
|
|
fast_err:4,
|
|
fast_val:4,
|
|
ieee_err:4,
|
|
ieee_val:4;
|
|
} DPML_EXCEPTION_RESPONSE;
|
|
|
|
typedef union {
|
|
signed int w;
|
|
float f;
|
|
double d;
|
|
long double ld;
|
|
} DPML_EXCEPTION_VALUE;
|
|
|
|
typedef struct {
|
|
signed int func_error_code;
|
|
void * context;
|
|
signed int platform_specific_err_code;
|
|
signed int environment;
|
|
void * ret_val_ptr;
|
|
char * name;
|
|
char data_type;
|
|
char dpml_error;
|
|
char mode;
|
|
DPML_EXCEPTION_VALUE ret_val;
|
|
DPML_EXCEPTION_VALUE args[4];
|
|
} DPML_EXCEPTION_RECORD;
|
|
|
|
typedef struct {
|
|
signed int exception_code,
|
|
error,
|
|
fp_num;
|
|
} __NT_ERROR_MAP;
|
|
|
|
typedef struct { char nt_prec, nt_format; } __NT_TYPE_MAP;
|
|
|
|
extern void * __dpml_exception(DPML_EXCEPTION_RECORD *);
|
|
extern double _except1(signed int, signed int, double, double, signed int);
|
|
extern double _except2(signed int, signed int, double, double, double, signed int);
|
|
extern signed int _ctrlfp(signed int, signed int);
|
|
extern void ReceiveSComplexResult(float*, float*);
|
|
extern void ReceiveTComplexResult(double*, double*);
|
|
|
|
const unsigned int __dpml_globals_table[] = {
|
|
0x00000000, 0x00000000, 0x00000000, 0xffff8000, 0x00000000, 0x00000000,
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000,
|
|
0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
|
|
0x00000000, 0x80000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x7ffeffff,
|
|
0xffffffff, 0xffffffff, 0xffffffff, 0xfffeffff, 0x00000000, 0x00000000,
|
|
0x00000000, 0x7fff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000,
|
|
0x00000000, 0x00000000, 0x00000000, 0x3f8f0000, 0x00000000, 0x00000000,
|
|
0x00000000, 0xbf8f0000, 0x00000000, 0x00000000, 0x00000000, 0x3fff0000,
|
|
0x00000000, 0x00000000, 0x00000000, 0xbfff0000, 0x00000000, 0xfff80000,
|
|
0x00000000, 0x00000000, 0x00000000, 0x80000000, 0x00000001, 0x00000000,
|
|
0x00000001, 0x80000000, 0xffffffff, 0x7fefffff, 0xffffffff, 0xffefffff,
|
|
0x00000000, 0x7ff00000, 0x00000000, 0xfff00000, 0x00000000, 0x3cb00000,
|
|
0x00000000, 0xbcb00000, 0x00000000, 0x3ff00000, 0x00000000, 0xbff00000,
|
|
0xffc00000, 0x00000000, 0x80000000, 0x00000001, 0x80000001, 0x7f7fffff,
|
|
0xff7fffff, 0x7f800000, 0xff800000, 0x34000000, 0xb4000000, 0x3f800000,
|
|
0xbf800000
|
|
};
|
|
|
|
const unsigned int __dpml_globals_offset_table[] = {
|
|
0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 216, 224,
|
|
232, 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 316, 320, 324, 328, 332,
|
|
336, 340, 344, 348, 352, 356, 360
|
|
};
|
|
|
|
static DPML_EXCEPTION_RESPONSE dpml_response_table[] = {
|
|
{0, 1, 1, 1, 0}, {1, 1, 1, 1, 0}, {2, 1, 1, 1, 0}, {3, 1, 1, 1, 0},
|
|
{4, 1, 1, 1, 0}, {8, 1, 1, 1, 0}, {8, 2, 5, 2, 7}, {8, 2, 6, 2, 8},
|
|
{9, 1, 1, 1, 0}, {9, 1, 1, 1, 0}, {9, 4, 1, 4, 1}, {10, 1, 1, 1, 0},
|
|
{10, 1, 1, 1, 0}, {10, 4, 1, 4, 1}, {11, 3, 5, 3, 7}, {39, 1, 1, 1, 0},
|
|
{39, 3, 5, 3, 7}, {12, 1, 1, 1, 0}, {13, 1, 1, 1, 0}, {14, 3, 5, 3, 7},
|
|
{33, 4, 1, 4, 1}, {33, 3, 5, 3, 7}, {33, 3, 6, 3, 8}, {33, 1, 1, 1, 0},
|
|
{33, 2, 5, 2, 7}, {34, 4, 1, 4, 1}, {34, 3, 5, 3, 7}, {34, 3, 6, 3, 8},
|
|
{34, 1, 1, 1, 0}, {34, 2, 5, 2, 7}, {16, 3, 5, 3, 7}, {16, 4, 1, 4, 1},
|
|
{16, 0, 7, 0, 7}, {16, 0, 1, 0, 1}, {17, 3, 5, 3, 7}, {17, 0, 7, 0, 7},
|
|
{17, 0, 12, 0, 12}, {38, 3, 5, 3, 7}, {38, 3, 6, 3, 8}, {38, 4, 1, 4, 1},
|
|
{47, 3, 5, 3, 7}, {47, 3, 6, 3, 8}, {47, 4, 1, 4, 1}, {47, 0, 7, 0, 7},
|
|
{47, 0, 8, 0, 8}, {47, 0, 1, 0, 1}, {47, 1, 1, 1, 0}, {37, 2, 6, 2, 8},
|
|
{18, 1, 1, 1, 0}, {18, 2, 6, 2, 8}, {19, 1, 1, 1, 0}, {19, 2, 6, 2, 8},
|
|
{20, 1, 1, 1, 0}, {20, 2, 6, 2, 8}, {45, 1, 1, 1, 0}, {45, 2, 6, 2, 8},
|
|
{21, 4, 1, 4, 1}, {21, 0, 1, 0, 1}, {21, 1, 1, 1, 0}, {40, 3, 5, 3, 7},
|
|
{40, 4, 1, 4, 1}, {22, 3, 5, 3, 7}, {22, 3, 6, 3, 8}, {22, 4, 1, 4, 1},
|
|
{22, 1, 1, 1, 0}, {22, 2, 6, 2, 8}, {22, 1, 1, 1, 0}, {22, 1, 1, 1, 0},
|
|
{22, 3, 6, 3, 8}, {22, 1, 1, 1, 0}, {22, 0, 7, 0, 7}, {22, 0, 7, 0, 7},
|
|
{22, 0, 8, 0, 8}, {22, 0, 7, 0, 7}, {22, 0, 1, 0, 1}, {22, 0, 1, 0, 1},
|
|
{41, 3, 5, 3, 7}, {41, 4, 1, 4, 1}, {41, 1, 1, 1, 0}, {41, 1, 1, 1, 0},
|
|
{48, 3, 5, 3, 7}, {48, 1, 1, 1, 0}, {23, 4, 1, 4, 1}, {23, 0, 1, 0, 1},
|
|
{23, 1, 1, 1, 0}, {24, 1, 1, 1, 0}, {31, 1, 1, 1, 0}, {32, 1, 1, 1, 0},
|
|
{32, 4, 1, 4, 1}, {25, 1, 1, 1, 0}, {25, 4, 1, 4, 1}, {26, 3, 5, 3, 7},
|
|
{26, 3, 6, 3, 8}, {26, 4, 1, 4, 1}, {27, 1, 1, 1, 0}, {28, 1, 1, 1, 0},
|
|
{29, 4, 1, 4, 1}, {29, 3, 5, 3, 7}, {29, 1, 1, 1, 0}, {29, 2, 5, 2, 7},
|
|
{30, 3, 5, 3, 7}, {30, 4, 1, 4, 1}, {35, 1, 1, 1, 0}, {36, 1, 1, 1, 0},
|
|
{36, 4, 1, 4, 1}, {49, 0, 1, 0, 1}, {50, 0, 1, 0, 1}, {51, 0, 1, 0, 1},
|
|
{42, 0, 1, 0, 1}, {43, 0, 1, 0, 1}, {44, 0, 1, 0, 1}, {42, 1, 1, 1, 0},
|
|
{42, 2, 6, 2, 8}, {43, 1, 1, 1, 0}, {43, 2, 6, 2, 8}, {43, 3, 6, 3, 8},
|
|
{44, 1, 1, 1, 0}, {44, 2, 6, 2, 8}, {44, 3, 6, 3, 8}, {46, 3, 5, 3, 7},
|
|
{46, 0, 7, 0, 7}, {46, 1, 1, 1, 0}, {46, 2, 5, 2, 7}, {46, 2, 5, 2, 7},
|
|
{53, 4, 1, 4, 1}
|
|
};
|
|
|
|
static __NT_ERROR_MAP __nt_errors[] = {
|
|
{ STATUS_FLOAT_INVALID_OPERATION, _DOMAIN, 8 },
|
|
{ STATUS_FLOAT_INVALID_OPERATION, _SING, 4 },
|
|
{ STATUS_FLOAT_OVERFLOW, _OVERFLOW, 1 },
|
|
{ STATUS_FLOAT_UNDERFLOW, _UNDERFLOW, 2 },
|
|
{ STATUS_FLOAT_INEXACT_RESULT, _PLOSS, 16 }
|
|
};
|
|
|
|
static __NT_TYPE_MAP __nt_type[] = {
|
|
{_FpPrecisionFull, _FpFormatFp128 },
|
|
{_FpPrecision53, _FpFormatFp64 },
|
|
{_FpPrecision24, _FpFormatFp32 }
|
|
};
|
|
|
|
static const unsigned int __nt_func_codes[] = {
|
|
|
|
((signed int)(_FpCodeAcos) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeAsin) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeAtan) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeAtan2) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeCabs) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeCos) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeCosh) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (2 | (2 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeExp) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeLog) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeLog10) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeFmod) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodePow) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeRemainder) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeSin) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeSinh) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeSquareRoot) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeTan) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeTanh) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (2 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (2 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (2 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (2 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeLogb) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeLdexp) << 18) | (2 | (1 << 3) | (1 << 6) | (0 << 9) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (4 | (2 << 3) | (1 << 6) | (1 << 9) | (1 << 12) | (1 << 15)),
|
|
((signed int)(_FpCodeNextafter) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (2 | (1 << 3) | (1 << 6) | (0 << 9) ),
|
|
((signed int)(_FpCodeY0) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeY1) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeYn) << 18) | (2 | (1 << 3) | (0 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (2 | (0 << 3) | (0 << 6) | (0 << 9) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (2 | (1 << 3) | (0 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeUnspecified) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeTruncate) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeFloor) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeCeil) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeFabs) << 18) | (1 | (1 << 3) | (1 << 6) ),
|
|
((signed int)(_FpCodeFrexp) << 18) | (2 | (1 << 3) | (1 << 6) | (3 << 9) ),
|
|
((signed int)(_FpCodeHypot) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9) ),
|
|
((signed int)(_FpCodeModf) << 18) | (2 | (1 << 3) | (1 << 6) | (1 << 9 ))
|
|
};
|
|
|
|
|
|
double
|
|
__to_double(DPML_EXCEPTION_VALUE *p, int generic_type, int float_type)
|
|
{
|
|
double d;
|
|
switch (generic_type) {
|
|
case 1:
|
|
switch (float_type) {
|
|
case 0: d = (double) p->ld; break;
|
|
case 1: d = (double) p->d; break;
|
|
case 2: d = (double) p->f; break;
|
|
}
|
|
break;
|
|
|
|
case 0:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
*((signed int *) &d) = p->w;
|
|
break;
|
|
|
|
case 2:
|
|
default:
|
|
d = (double) 0.0;
|
|
break;
|
|
}
|
|
return d;
|
|
}
|
|
|
|
static void
|
|
DPML_DO_SIDE_EFFECTS_NAME(DPML_EXCEPTION_RECORD *p)
|
|
{
|
|
signed int nt_fpe_num, nt_op, operand_desc, func_code, float_type;
|
|
signed int fpcsr;
|
|
double arg1, arg2, result;
|
|
|
|
func_code = dpml_response_table[p->func_error_code].func;
|
|
nt_op = (__nt_func_codes[func_code] >> 18);
|
|
nt_fpe_num = __nt_errors[(p->dpml_error)-1].fp_num;
|
|
fpcsr = _ctrlfp(-1, -1);
|
|
if (nt_fpe_num & (2 | 1)) {
|
|
nt_fpe_num |= 16;
|
|
}
|
|
|
|
float_type = p->data_type;
|
|
operand_desc = (__nt_func_codes[func_code] & ((((unsigned int)1 << (18)) - 1) << 0));
|
|
result = __to_double((DPML_EXCEPTION_VALUE *) p->ret_val_ptr, (((operand_desc) >> 3) & 0x7), float_type);
|
|
arg1 = __to_double(&p->args[0], (((operand_desc) >> 6) & 0x7), float_type);
|
|
|
|
if (((operand_desc) & 0x7) == 1) {
|
|
result = _except1(nt_fpe_num, nt_op, arg1, result, fpcsr);
|
|
|
|
} else {
|
|
arg2 = __to_double(&p->args[1], (((operand_desc) >> 9) & 0x7), float_type);
|
|
result = _except2(nt_fpe_num, nt_op, arg1, arg2, result, fpcsr);
|
|
}
|
|
|
|
if ((((operand_desc) >> 3) & 0x7) == 1) {
|
|
switch (float_type) {
|
|
case 0: p->ret_val.ld = ((long double) result); break;
|
|
case 1: p->ret_val.d = ((double) result); break;
|
|
case 2: p->ret_val.f = ((float) result); break;
|
|
}
|
|
p->ret_val_ptr = ((void *) &(p->ret_val));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
#if _NTSUBSET_
|
|
|
|
//
|
|
// Cannot call _controlfp in ntdll subset.
|
|
//
|
|
|
|
static void
|
|
dpml_get_environment(DPML_EXCEPTION_RECORD *p)
|
|
{
|
|
signed int fpcsr;
|
|
|
|
p->environment = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
#else
|
|
|
|
static void
|
|
dpml_get_environment(DPML_EXCEPTION_RECORD *p)
|
|
{
|
|
signed int _controlfp(signed int, signed int);
|
|
signed int fpcsr;
|
|
|
|
fpcsr = _controlfp(0, 0);
|
|
/* bit reverse sticky, exception, status bytes */
|
|
(fpcsr) = (((fpcsr) & 0xf0f0f0f0) >> 4) | (((fpcsr) & 0x0f0f0f0f) << 4);
|
|
(fpcsr) = (((fpcsr) & 0xcccccccc) >> 2) | (((fpcsr) & 0x33333333) << 2);
|
|
(fpcsr) = (((fpcsr) & 0xaaaaaaaa) >> 1) | (((fpcsr) & 0x55555555) << 1);
|
|
p->environment = ((fpcsr >> 3) | ((unsigned int)1 << (7)));
|
|
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
void *
|
|
__dpml_exception(DPML_EXCEPTION_RECORD *p)
|
|
{
|
|
signed int err = p->func_error_code;
|
|
p->data_type = (((err) >> (32 - 5)));
|
|
p->func_error_code =
|
|
(((err) & ~((((unsigned int)1 << (5)) - 1) << ((32 - 5)))));
|
|
dpml_get_environment(p);
|
|
if (err < 0) {
|
|
return (void *) p->environment;
|
|
}
|
|
|
|
{
|
|
signed int e, v, type;
|
|
e = p->func_error_code;
|
|
if (((unsigned int)1 << (7)) & p->environment) {
|
|
v = dpml_response_table[e].ieee_val;
|
|
e = dpml_response_table[e].ieee_err;
|
|
|
|
} else {
|
|
v = dpml_response_table[e].fast_val;
|
|
e = dpml_response_table[e].fast_err;
|
|
}
|
|
p->dpml_error = e;
|
|
type = p->data_type;
|
|
p->ret_val_ptr =
|
|
(((void *) ((char *) __dpml_globals_table +
|
|
__dpml_globals_offset_table[type*13 + v])));
|
|
}
|
|
|
|
if (p->dpml_error != 0) {
|
|
DPML_DO_SIDE_EFFECTS_NAME(p);
|
|
}
|
|
|
|
return p->ret_val_ptr;
|
|
}
|