aboutsummaryrefslogtreecommitdiff
path: root/Src/ns-eel/nseel-cfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/ns-eel/nseel-cfunc.c')
-rw-r--r--Src/ns-eel/nseel-cfunc.c776
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