diff options
Diffstat (limited to 'Src/ns-eel/nseel-cfunc.c')
-rw-r--r-- | Src/ns-eel/nseel-cfunc.c | 776 |
1 files changed, 776 insertions, 0 deletions
diff --git a/Src/ns-eel/nseel-cfunc.c b/Src/ns-eel/nseel-cfunc.c new file mode 100644 index 00000000..919f9407 --- /dev/null +++ b/Src/ns-eel/nseel-cfunc.c @@ -0,0 +1,776 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + nseel-cfunc.c: assembly/C implementation of operator/function templates + This file should be ideally compiled with optimizations towards "minimize size" + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +#include <windows.h> +#include <math.h> +#include "ns-eel-int.h" + + +// these are used by our assembly code +static float g_cmpaddtab[2]={0.0,1.0}; +static float g_signs[2]={1.0,-1.0}; +static double g_closefact = 0.00001; +static float g_half=0.5; +static float negativezeropointfive=-0.5f; +static float onepointfive=1.5f; + + + +/// functions called by built code + +#define isnonzero(x) (fabs(x) > g_closefact) +#pragma optimize( "", off ) +//--------------------------------------------------------------------------------------------------------------- +static double NSEEL_CGEN_CALL _rand(double *x) +{ + if (*x < 1.0) *x=1.0; + return (double)(rand()%(int)max(*x,1.0)); +} + +//--------------------------------------------------------------------------------------------------------------- +static double NSEEL_CGEN_CALL _band(double *var, double *var2) +{ + return isnonzero(*var) && isnonzero(*var2) ? 1 : 0; +} + +//--------------------------------------------------------------------------------------------------------------- +static double NSEEL_CGEN_CALL _bor(double *var, double *var2) +{ + return isnonzero(*var) || isnonzero(*var2) ? 1 : 0; +} + +//--------------------------------------------------------------------------------------------------------------- +static double NSEEL_CGEN_CALL _sig(double *x, double *constraint) +{ + double t = (1+exp(-*x * (*constraint))); + return isnonzero(t) ? 1.0/t : 0; +} + + +// end functions called by inline code + +// these make room on the stack for local variables, but do not need to +// worry about trashing ebp, since none of our code uses ebp and there's +// a pushad+popad surrounding the call + + +static double (*__asin)(double) = &asin; +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_asin(void) +{ + FUNC1_ENTER + + *__nextBlock = __asin(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_asin_end(void) {} + +static double (*__acos)(double) = &acos; +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_acos(void) +{ + FUNC1_ENTER + + *__nextBlock = __acos(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_acos_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (*__atan)(double) = &atan; +__declspec ( naked ) void nseel_asm_atan(void) +{ + FUNC1_ENTER + + *__nextBlock = __atan(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_atan_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (*__atan2)(double,double) = &atan2; +__declspec ( naked ) void nseel_asm_atan2(void) +{ + FUNC2_ENTER + + *__nextBlock = __atan2(*parm_b, *parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_atan2_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +static double (NSEEL_CGEN_CALL * __sig)(double *,double *) = &_sig; +__declspec ( naked ) void nseel_asm_sig(void) +{ + FUNC2_ENTER + + *__nextBlock = __sig(parm_b, parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_sig_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (NSEEL_CGEN_CALL *__rand)(double *) = &_rand; +__declspec ( naked ) void nseel_asm_rand(void) +{ + FUNC1_ENTER + + *__nextBlock = __rand(parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_rand_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (NSEEL_CGEN_CALL *__band)(double *,double *) = &_band; +__declspec ( naked ) void nseel_asm_band(void) +{ + FUNC2_ENTER + + *__nextBlock = __band(parm_b, parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_band_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double ( NSEEL_CGEN_CALL *__bor)(double *,double *) = &_bor; +__declspec ( naked ) void nseel_asm_bor(void) +{ + FUNC2_ENTER + + *__nextBlock = __bor(parm_b, parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_bor_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (* __pow)(double,double) = &pow; +__declspec ( naked ) void nseel_asm_pow(void) +{ + FUNC2_ENTER + + *__nextBlock = __pow(*parm_b, *parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_pow_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (*__exp)(double) = &exp; +__declspec ( naked ) void nseel_asm_exp(void) +{ + FUNC1_ENTER + + *__nextBlock = __exp(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_exp_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +//static double (*__floor)(double) = &floor; +__declspec ( naked ) void nseel_asm_floor(void) +{ + FUNC1_ENTER + + *__nextBlock = __floor(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_floor_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +//static double (*__ceil)(double) = &ceil; +__declspec ( naked ) void nseel_asm_ceil(void) +{ + FUNC1_ENTER + + *__nextBlock = __ceil(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_ceil_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- + + + + +// do nothing, eh +__declspec ( naked ) void nseel_asm_exec2(void) +{ +} +__declspec ( naked ) void nseel_asm_exec2_end(void) { } + + + +__declspec ( naked ) void nseel_asm_invsqrt(void) +{ + __asm + { + fld qword ptr [eax] + + mov edx, 0x5f3759df + fst dword ptr [esi] + // floating point stack has input, as does [eax] + fmul dword ptr [negativezeropointfive] + mov ecx, [esi] + sar ecx, 1 + sub edx, ecx + mov [esi], edx + + // st(0) = input, [eax] has x + fmul dword ptr [esi] + + fmul dword ptr [esi] + + fadd dword ptr [onepointfive] + + fmul dword ptr [esi] + mov eax, esi + + fstp qword ptr [esi] + + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_invsqrt_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sin(void) +{ + __asm + { + fld qword ptr [eax] + fsin + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_sin_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_cos(void) +{ + __asm + { + fld qword ptr [eax] + fcos + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_cos_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_tan(void) +{ + __asm + { + fld qword ptr [eax] + fsincos + fdiv + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_tan_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sqr(void) +{ + __asm + { + fld qword ptr [eax] + fmul st(0), st(0) + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_sqr_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sqrt(void) +{ + __asm + { + fld qword ptr [eax] + fabs + fsqrt + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_sqrt_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_log(void) +{ + __asm + { + fld1 + fldl2e + fdiv + fld qword ptr [eax] + mov eax, esi + fyl2x + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_log_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_log10(void) +{ + __asm + { + fld1 + fldl2t + fdiv + fld qword ptr [eax] + mov eax, esi + fyl2x + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_log10_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_abs(void) +{ + __asm + { + fld qword ptr [eax] + fabs + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_abs_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_assign(void) +{ + __asm + { + fld qword ptr [eax] + fstp qword ptr [ebx] + } +} +__declspec ( naked ) void nseel_asm_assign_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_add(void) +{ + __asm + { + fld qword ptr [eax] + fadd qword ptr [ebx] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_add_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sub(void) +{ + __asm + { + fld qword ptr [ebx] + fsub qword ptr [eax] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_sub_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_mul(void) +{ + __asm + { + fld qword ptr [ebx] + fmul qword ptr [eax] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_mul_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_div(void) +{ + __asm + { + fld qword ptr [ebx] + fdiv qword ptr [eax] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_div_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_mod(void) +{ + __asm + { + fld qword ptr [ebx] + + fld qword ptr [eax] + fsub dword ptr [g_cmpaddtab+4] + fabs + fadd qword ptr [eax] + fadd dword ptr [g_cmpaddtab+4] + + fmul dword ptr [g_half] + + fistp dword ptr [esi] + fistp dword ptr [esi+4] + mov eax, [esi+4] + xor edx, edx + div dword ptr [esi] + mov [esi], edx + fild dword ptr [esi] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + + } +} +__declspec ( naked ) void nseel_asm_mod_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_or(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + fistp qword ptr [esi] + fistp qword ptr [esi+8] + mov ebx, [esi+8] + or [esi], ebx + mov ebx, [esi+12] + or [esi+4], ebx + fild qword ptr [esi] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_or_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_and(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + + fistp qword ptr [esi] + fistp qword ptr [esi+8] + mov ebx, [esi+8] + and [esi], ebx + mov ebx, [esi+12] + and [esi+4], ebx + fild qword ptr [esi] + fstp qword ptr [esi] + + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_and_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_uplus(void) // this is the same as doing nothing, it seems +{ +#if 0 + __asm + { + mov ebx, nextBlock + mov ecx, [eax] + mov [ebx], ecx + mov ecx, [eax+4] + mov [ebx+4], ecx + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx + } +#endif +} +__declspec ( naked ) void nseel_asm_uplus_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_uminus(void) +{ + __asm + { + mov ecx, [eax] + mov ebx, [eax+4] + xor ebx, 0x80000000 + mov [esi], ecx + mov [esi+4], ebx + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_uminus_end(void) {} + + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sign(void) +{ + __asm + { + mov ecx, [eax+4] + mov edx, [eax] + test edx, 0FFFFFFFFh + jnz nonzero + + // high dword (minus sign bit) is zero + test ecx, 07FFFFFFFh + jz zero // zero zero, return the value passed directly + +nonzero: + shr ecx, 31 + + fld dword ptr [g_signs+ecx*4] + + fstp qword ptr [esi] + + mov eax, esi + add esi, 8 +zero: + } +} +__declspec ( naked ) void nseel_asm_sign_end(void) {} + + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_bnot(void) +{ + __asm + { + fld qword ptr [eax] + fabs + fcomp qword ptr [g_closefact] + fstsw ax + shr eax, 6 + and eax, (1<<2) + fld dword ptr [g_cmpaddtab+eax] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_bnot_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_if(void) +{ + __asm + { + fld qword ptr [eax] + fabs + fcomp qword ptr [g_closefact] + fstsw ax + + shr eax, 6 + + mov dword ptr [esi], 0FFFFFFFFh + mov dword ptr [esi+4], 0FFFFFFFFh + + and eax, (1<<2) + + mov eax, [esi+eax] + + call eax // call the proper function + + // at this point, the return value will be in eax, as desired + } +} +__declspec ( naked ) void nseel_asm_if_end(void) {} + +#ifdef NSEEL_LOOPFUNC_SUPPORT +#ifndef NSEEL_LOOPFUNC_SUPPORT_MAXLEN +#define NSEEL_LOOPFUNC_SUPPORT_MAXLEN (4096) +#endif +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_repeat(void) +{ + __asm + { + fld qword ptr [eax] + fistp dword ptr [esi] + mov ecx, [esi] + cmp ecx, 1 + jl skip + cmp ecx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN + jl again + mov ecx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN +again: + push ecx + push esi // revert back to last temp workspace + mov ecx, 0FFFFFFFFh + call ecx + pop esi + pop ecx + dec ecx + jnz again +skip: + } +} +__declspec ( naked ) void nseel_asm_repeat_end(void) {} +#endif + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_equal(void) +{ + __asm + { + fld qword ptr [eax] + fsub qword ptr [ebx] + fabs + fcomp qword ptr [g_closefact] + fstsw ax + shr eax, 6 + and eax, (1<<2) + fld dword ptr [g_cmpaddtab+eax] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_equal_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_below(void) +{ + __asm + { + fld qword ptr [ebx] + fcomp qword ptr [eax] + fstsw ax + shr eax, 6 + and eax, (1<<2) + fld dword ptr [g_cmpaddtab+eax] + + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_below_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_above(void) +{ + __asm + { + fld qword ptr [eax] + fcomp qword ptr [ebx] + fstsw ax + shr eax, 6 + and eax, (1<<2) + fld dword ptr [g_cmpaddtab+eax] + + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_above_end(void) {} + + +__declspec ( naked ) void nseel_asm_min(void) +{ + __asm + { + fld qword ptr [eax] + fld qword ptr [ebx] + fld st(1) + fsub st(0), st(1) + fabs // stack contains fabs(1-2),1,2 + fchs + fadd + fadd + fmul dword ptr [g_half] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_min_end(void) {} + +__declspec ( naked ) void nseel_asm_max(void) +{ + __asm + { + fld qword ptr [eax] + fld qword ptr [ebx] + fld st(1) + fsub st(0), st(1) + fabs // stack contains fabs(1-2),1,2 + fadd + fadd + fmul dword ptr [g_half] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_max_end(void) {} + +#pragma optimize( "", on )
\ No newline at end of file |