|
Odamex
Setting the Standard in Multiplayer Doom
|
00001 // Emacs style mode select -*- C++ -*- 00002 //----------------------------------------------------------------------------- 00003 // 00004 // $Id: m_fixed.h 1788 2010-08-24 04:42:57Z russellrice $ 00005 // 00006 // Copyright (C) 1993-1996 by id Software, Inc. 00007 // Copyright (C) 2006-2010 by The Odamex Team. 00008 // 00009 // This program is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // This program is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // DESCRIPTION: 00020 // Fixed point arithemtics, implementation. 00021 // 00022 //----------------------------------------------------------------------------- 00023 00024 00025 #ifndef __M_FIXED__ 00026 #define __M_FIXED__ 00027 00028 #include <stdlib.h> 00029 #include "doomtype.h" 00030 00031 // 00032 // Fixed point, 32bit as 16.16. 00033 // 00034 #define FRACBITS 16 00035 #define FRACUNIT (1<<FRACBITS) 00036 00037 typedef int fixed_t; // fixed 16.16 00038 typedef unsigned int dsfixed_t; // fixedpt used by span drawer 00039 00040 extern "C" fixed_t FixedMul_ASM (fixed_t a, fixed_t b); 00041 extern "C" fixed_t STACK_ARGS FixedDiv_ASM (fixed_t a, fixed_t b); 00042 fixed_t FixedMul_C (fixed_t a, fixed_t b); 00043 fixed_t FixedDiv_C (fixed_t a, fixed_t b); 00044 00045 #ifdef ALPHA 00046 inline fixed_t FixedMul (fixed_t a, fixed_t b) 00047 { 00048 return (fixed_t)(((long)a * (long)b) >> 16); 00049 } 00050 00051 inline fixed_t FixedDiv (fixed_t a, fixed_t b) 00052 { 00053 if (abs(a) >> 14 >= abs(b)) 00054 return (a^b)<0 ? MININT : MAXINT; 00055 return (fixed_t)((((long)a) << 16) / b); 00056 } 00057 00058 #else 00059 00060 #ifdef USEASM 00061 00062 #if defined(_MSC_VER) 00063 00064 __inline fixed_t FixedMul (fixed_t a, fixed_t b) 00065 { 00066 fixed_t result; 00067 __asm { 00068 mov eax,[a] 00069 imul [b] 00070 shrd eax,edx,16 00071 mov [result],eax 00072 } 00073 return result; 00074 } 00075 00076 #if 1 00077 // Inlining FixedDiv with VC++ generates too many bad optimizations. 00078 #define FixedDiv(a,b) FixedDiv_ASM(a,b) 00079 #else 00080 __inline fixed_t FixedDiv (fixed_t a, fixed_t b) 00081 { 00082 if (abs(a) >> 14 >= abs(b)) 00083 return (a^b)<0 ? MININT : MAXINT; 00084 else 00085 { 00086 fixed_t result; 00087 00088 __asm { 00089 mov eax,[a] 00090 mov edx,[a] 00091 sar edx,16 00092 shl eax,16 00093 idiv [b] 00094 mov [result],eax 00095 } 00096 return result; 00097 } 00098 } 00099 #endif 00100 00101 #else 00102 00103 #define FixedMul(a,b) FixedMul_ASM(a,b) 00104 #define FixedDiv(a,b) FixedDiv_ASM(a,b) 00105 00106 #endif 00107 00108 #else // !USEASM 00109 #define FixedMul(a,b) FixedMul_C(a,b) 00110 #define FixedDiv(a,b) FixedDiv_C(a,b) 00111 #endif 00112 00113 #endif // !ALPHA 00114 00115 #endif 00116 00117