📄 fpu87.cpp
字号:
/************************************************************************************************************************************************************** **** equal III the graphic builder **** **** Copyright (C) 2003 Oleksiy Pylypenko **** **** This file may be distributed and/or modified under the terms of the **** GNU General Public License version 2 as published by the Free Software **** Foundation and appearing in the file license included in the **** packaging of this file. **** **** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE **** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. **** **** Contact earthman@inbox.ru if any conditions of this licensing are **** not clear to you. **** **** ********************************************************************************* *****************************************************************************/#include "equal_headers.h"#include "fpu87.h"// some FPU instructions/typedef void (*exceptionHandler)(void);class fpuArithmetic : public mashineCode{public: void ASM_mov_pESP_EAX(void){code(0x89);code(0x04);code(0x24);} void ASM_mov_EAX_MEM(void *MEM){code(0xA1);push_ptr(MEM);} // [v] -> eax void ASM_mov_EAX_VAL(void *MEM){code(0xB8);push_ptr(MEM);} // v -> eax void ASM_mov_EAX_VAL(unsigned long v){code(0xB8);push_dword(v);} // v -> eax void ASM_mov_pEAX_VAL(unsigned long v){code(0xC7);code(0x00);push_dword(v);} //v -> [eax] void ASM_fadd(void){code(0xDE);code(0xC1);} // a <== fpu_stack,b <== fpu_stack, a+b ==> fpu_stack void ASM_fsub(void){code(0xDE);code(0xE9);} // a <== fpu_stack,b <== fpu_stack, a-b ==> fpu_stack void ASM_fmul(void){code(0xDE);code(0xC9);} // a <== fpu_stack,b <== fpu_stack, a*b ==> fpu_stack void ASM_fdiv(void){code(0xDE);code(0xF9);} // a <== fpu_stack,b <== fpu_stack, a/b ==> fpu_stack void ASM_fpush(double *a){ASM_mov_EAX_VAL(a);ASM_fld_eax();} // a ==> fpu_stack void ASM_fpop(double *a){ASM_mov_EAX_VAL(a);ASM_fstp_eax();} // a <== fpu_stack void ASM_fabs(void){code(0xD9);code(0xE1);} // a <== fpu_stack,fabs(a) ==> fpu_stack void ASM_fsin(void){code(0xD9);code(0xFE);} // a <== fpu_stack,sin(a) ==> fpu_stack void ASM_fcos(void){code(0xD9);code(0xFF);} // a <== fpu_stack,cos(a) ==> fpu_stack void ASM_fsqrt(void){code(0xD9);code(0xFA);} // a <== fpu_stack,sqrt(a) ==> fpu_stack void ASM_fneg(void){code(0xD9);code(0xE0);} // a <== fpu_stack,-a ==> fpu_stack void ASM_fld_eax(void){code(0xDD);code(0x00);} // [eax] ==> fpu_stack void ASM_fstp_eax(void){code(0xDD);code(0x18);} // [eax] <== fpu_stack// void ASM_return(unsigned long d){mov_EAX_VAL(d);} // returns value d (eax - is ret. value) void ASM_ret(void){code(0xC3);} // finishes procedure call void ASM_sub_esp(char bytes){code(0x83);code(0xEC);code(bytes);} // reserves some space in CPU stack void ASM_add_esp(char bytes){code(0x83);code(0xC4);code(bytes);} // return space in CPU stack void ASM_fld_esp(void){code(0xDD);code(0x1C);code(0x24);} // a <== fpu_stack, a ==> cpu_stack void ASM_prolog(void){//prolog code(0x55); //push ebp code(0x53); //push ebx code(0x56); //push esi code(0x57); //push edi } void ASM_epilog(void){//epilog code(0x5F); //pop edi code(0x5E); //pop esi code(0x5B); //pop ebx code(0x5D); //pop ebp } //void ASM_fchs(void){code(0xD9);code(0xE0); unsigned long exceptionEsp; unsigned long exception; exceptionHandler exceptionCodePtr; unsigned long exceptionCodeShortPtr; int IsException(void){ return exception; } // calls C function by ptr with nparams count of params void ASM_c_call(void *ptr,int nparams) { // arguments for(int i = 0;i < nparams;i++) ASM_sub_esp(sizeof(double)),ASM_fld_esp(); // exceptionHandler ptr ASM_sub_esp(sizeof(exceptionCodePtr)); ASM_mov_EAX_MEM(&exceptionCodePtr); ASM_mov_pESP_EAX(); ASM_mov_EAX_VAL(ptr); // set ptr to eax code(0xFF);code(0xD0); // call eax ASM_add_esp((int)(sizeof(double) * nparams) + sizeof(exceptionCodePtr) ); } void ASM_save_esp(unsigned long *where){ ASM_mov_EAX_VAL(where); code(0x89);code(0x20);//esp -> [eax] } void ASM_load_esp(unsigned long *where){ ASM_mov_EAX_VAL(where); code(0x8B);code(0x20);//[eax] -> esp } void initExceptions(void){ ASM_save_esp(&exceptionEsp); ASM_mov_EAX_VAL(&exception); ASM_mov_pEAX_VAL(0); } void pushException(void){ exceptionCodeShortPtr = size(); ASM_load_esp(&exceptionEsp); ASM_mov_EAX_VAL(&exception); ASM_mov_pEAX_VAL(1); //make chkesp happy// code(0x8B);code(0xF4);//mov esi,esp// code(0x83);code(0xC6);code(0x04);//add esi,4 ASM_epilog(); ASM_ret(); } void preExecute(byte *codes){ exceptionCodePtr = exceptionHandler((unsigned long)codes + exceptionCodeShortPtr); }};// Some handlers for x86 executornamespace x86_exec_ns{ namespace mymath{ const double log10 = log(10.); double mylog01(exceptionHandler eh,double a){ if(a <= 0.)eh(); return log(a)/log10; } double mylog02(exceptionHandler eh,double a,double b){ if(a <= 0. || b <= 0.)eh(); return log(a)/log(b); } double anexp = ::exp(1.); double log_e = log(anexp); double ln(exceptionHandler eh,double a){ if(a < 0.)eh(); //if(a <= 0.0001)return 1./a; return log(a)/log_e; } double Pi = ::asin(1.) * 2.; double myfloor(exceptionHandler,double x){// if(fabs(double(long(x)) - x) < 0.0)// return x; return floor(x); } double xfloor(exceptionHandler eh,double x){ return x - myfloor(eh,x); } double fact(exceptionHandler,double x){ /* if((double)((int)(x)) == x) return double(ifact(double(x)));*/ if(x < 0)return 1.; double res = 1; double D = 0; int nfact = 2; int fact = 2; double iN = x; double N = x; for(int i = 0;i < 20;i++) { iN--; if(iN < 0)return res; N *= iN; D += 1 / double(nfact); res += D * N; fact++; nfact *= -fact; } return res; } double fmod(exceptionHandler eh,double a,double b){ if(fabs(b) < 1E-10) eh(); double r = ::fmod(::fmod(a,b)+b,b); return r; } double pow(exceptionHandler eh,double a,double b){ if(a < 0. && fabs(b-floor(b+0.00001))>0.000001) eh(); if(b < 0. && fabs(a) < 0.00000000001) eh(); return ::pow(a,b); } double mygreater(exceptionHandler,double a,double b){ return b-a; } double asin(exceptionHandler eh,double x){ if(fabs(x) > 1.)eh(); return ::asin(x); } double acos(exceptionHandler eh,double x){ if(fabs(x) > 1.)eh(); return ::acos(x); } double sqrt(exceptionHandler eh,double x){ if(x < 0.)eh(); return ::sqrt(x); } double atan2(exceptionHandler,double x,double y){ double r = ::atan2(x,y); if(r < 0)r += Pi * 2.; return r; } double div(exceptionHandler eh,double x,double y){ if(fabs(y)<0.00000000001) eh(); return x/y; } double min(exceptionHandler,double x,double y){ if(x < y)return x; return y; } double max(exceptionHandler,double x,double y){ if(x < y)return y; return x; }/* double tan(exceptionHandler eh,double x){ if(fabs(fmod(eh,x,Pi)-Pi/2.) < 0.04) eh(); return ::tan(x); }*/ #define ONE_PARAM(x) double x(exceptionHandler,double z){return ::x(z);} #define TWO_PARAMS(x) double x(exceptionHandler,double z,double y){return ::x(z,y);} ONE_PARAM(exp) ONE_PARAM(sinh) ONE_PARAM(cosh) ONE_PARAM(tanh) ONE_PARAM(tan) ONE_PARAM(ceil) //ONE_PARAM(floor)// ONE_PARAM(acos)// ONE_PARAM(asin) ONE_PARAM(atan)// TWO_PARAMS(pow) #undef ONE_PARAM #undef TWO_PARAMS } void log01(fpuArithmetic &myfpu){myfpu.ASM_c_call((void*)mymath::mylog01,1);} void log02(fpuArithmetic &myfpu){myfpu.ASM_c_call((void*)mymath::mylog02,2);} void Pi(fpuArithmetic &myfpu){myfpu.ASM_fpush(&mymath::Pi);} void e(fpuArithmetic &myfpu){myfpu.ASM_fpush(&mymath::anexp);} void add(fpuArithmetic &myfpu){myfpu.ASM_fadd();} void sub(fpuArithmetic &myfpu){myfpu.ASM_fsub();} void mul(fpuArithmetic &myfpu){myfpu.ASM_fmul();}// void div(fpuArithmetic &f){f.ASM_fdiv();} void add01(fpuArithmetic & /*myfpu*/){} void sub01(fpuArithmetic &myfpu){ myfpu.ASM_fneg();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -