// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman // Ken Silverman's official web site: "http://www.advsys.net/ken" // See the included license file "BUILDLIC.TXT" for license info. // // This file is based on pragmas.h from Ken Silverman's original Build // source code release but is meant for use with GCC instead of Watcom C. // // Some of the inline assembly has been turned into C code, because // modern compilers are smart enough to produce code at least as good as // Ken's inline assembly. // // I can come up with several different operand constraints for the // following that work just fine when used all by themselves, but // when I concatenate them together so that the compiler can choose // between them, I get the following (but only if enough parameters // are passed as the result of some operations instead of as // variables/constants--e.g. DMulScale16 (a*2, b*2, c*2, d*2) instead of // DMulScale16 (a, b, c, d)): // // `asm' operand requires impossible reload // // Why? #include #ifndef alloca // MinGW does not seem to come with alloca defined. #define alloca __builtin_alloca #endif static inline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c) { SDWORD result, dummy; asm volatile ("imull %3\n\t" "idivl %4" : "=a,a,a,a,a,a" (result), "=&d,&d,&d,&d,d,d" (dummy) : "a,a,a,a,a,a" (a), "m,r,m,r,d,d" (b), "r,r,m,m,r,m" (c) : "%cc" ); return result; } static inline SDWORD MulScale (SDWORD a, SDWORD b, SDWORD c) { SDWORD result, dummy; asm volatile ("imull %3\n\t" "shrdl %b4,%1,%0" : "=a,a,a,a" (result), "=d,d,d,d" (dummy) : "a,a,a,a" (a), "m,r,m,r" (b), "c,c,I,I" (c) : "%cc" ); return result; } #define MAKECONSTMulScale(s) \ static inline SDWORD MulScale##s (SDWORD a, SDWORD b) { return ((SQWORD)a * b) >> s; } MAKECONSTMulScale(1) MAKECONSTMulScale(2) MAKECONSTMulScale(3) MAKECONSTMulScale(4) MAKECONSTMulScale(5) MAKECONSTMulScale(6) MAKECONSTMulScale(7) MAKECONSTMulScale(8) MAKECONSTMulScale(9) MAKECONSTMulScale(10) MAKECONSTMulScale(11) MAKECONSTMulScale(12) MAKECONSTMulScale(13) MAKECONSTMulScale(14) MAKECONSTMulScale(15) MAKECONSTMulScale(16) MAKECONSTMulScale(17) MAKECONSTMulScale(18) MAKECONSTMulScale(19) MAKECONSTMulScale(20) MAKECONSTMulScale(21) MAKECONSTMulScale(22) MAKECONSTMulScale(23) MAKECONSTMulScale(24) MAKECONSTMulScale(25) MAKECONSTMulScale(26) MAKECONSTMulScale(27) MAKECONSTMulScale(28) MAKECONSTMulScale(29) MAKECONSTMulScale(30) MAKECONSTMulScale(31) MAKECONSTMulScale(32) #undef MAKECONSTMulScale static inline DWORD UMulScale16(DWORD a, DWORD b) { return ((QWORD)a * b) >> 16; } #define MAKECONSTDMulScale(s) \ static inline SDWORD DMulScale##s (SDWORD a, SDWORD b, SDWORD c, SDWORD d) \ { \ return (((SQWORD)a * b) + ((SQWORD)c * d)) >> s; \ } MAKECONSTDMulScale(1) MAKECONSTDMulScale(2) MAKECONSTDMulScale(3) MAKECONSTDMulScale(4) MAKECONSTDMulScale(5) MAKECONSTDMulScale(6) MAKECONSTDMulScale(7) MAKECONSTDMulScale(8) MAKECONSTDMulScale(9) MAKECONSTDMulScale(10) MAKECONSTDMulScale(11) MAKECONSTDMulScale(12) MAKECONSTDMulScale(13) MAKECONSTDMulScale(14) MAKECONSTDMulScale(15) MAKECONSTDMulScale(16) MAKECONSTDMulScale(17) MAKECONSTDMulScale(18) MAKECONSTDMulScale(19) MAKECONSTDMulScale(20) MAKECONSTDMulScale(21) MAKECONSTDMulScale(22) MAKECONSTDMulScale(23) MAKECONSTDMulScale(24) MAKECONSTDMulScale(25) MAKECONSTDMulScale(26) MAKECONSTDMulScale(27) MAKECONSTDMulScale(28) MAKECONSTDMulScale(29) MAKECONSTDMulScale(30) MAKECONSTDMulScale(31) MAKECONSTDMulScale(32) #undef MAKECONSTDMulScale #define MAKECONSTTMulScale(s) \ static inline SDWORD TMulScale##s (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD ee) \ { \ return (((SQWORD)a * b) + ((SQWORD)c * d) + ((SQWORD)e * ee)) >> s; \ } MAKECONSTTMulScale(1) MAKECONSTTMulScale(2) MAKECONSTTMulScale(3) MAKECONSTTMulScale(4) MAKECONSTTMulScale(5) MAKECONSTTMulScale(6) MAKECONSTTMulScale(7) MAKECONSTTMulScale(8) MAKECONSTTMulScale(9) MAKECONSTTMulScale(10) MAKECONSTTMulScale(11) MAKECONSTTMulScale(12) MAKECONSTTMulScale(13) MAKECONSTTMulScale(14) MAKECONSTTMulScale(15) MAKECONSTTMulScale(16) MAKECONSTTMulScale(17) MAKECONSTTMulScale(18) MAKECONSTTMulScale(19) MAKECONSTTMulScale(20) MAKECONSTTMulScale(21) MAKECONSTTMulScale(22) MAKECONSTTMulScale(23) MAKECONSTTMulScale(24) MAKECONSTTMulScale(25) MAKECONSTTMulScale(26) MAKECONSTTMulScale(27) MAKECONSTTMulScale(28) MAKECONSTTMulScale(29) MAKECONSTTMulScale(30) MAKECONSTTMulScale(31) MAKECONSTTMulScale(32) #undef MAKECONSTTMulScale static inline SDWORD BoundMulScale (SDWORD a, SDWORD b, SDWORD c) { union { long long big; struct { int l, h; }; } u; u.big = ((long long)a * b) >> c; if ((u.h ^ u.l) < 0 || (unsigned int)(u.h+1) > 1) return (u.h >> 31) ^ 0x7fffffff; return u.l; } static inline SDWORD DivScale (SDWORD a, SDWORD b, SDWORD c) { SDWORD result, dummy; SDWORD lo = a << c; SDWORD hi = a >> (-c); asm volatile ("idivl %4" :"=a" (result), "=d" (dummy) : "a" (lo), "d" (hi), "r" (b) : "%cc"); return result; } static inline SDWORD DivScale1 (SDWORD a, SDWORD b) { SDWORD result, dummy; asm volatile ("addl %%eax,%%eax\n\t" "sbbl %%edx,%%edx\n\t" "idivl %3" :"=a,a" (result), "=&d,d" (dummy) : "a,a" (a), "r,m" (b) : "%cc"); return result; } #define MAKECONSTDivScale(s) \ static inline SDWORD DivScale##s (SDWORD a, SDWORD b) \ { \ SDWORD result, dummy; \ asm volatile \ ("idivl %4" \ :"=a,a" (result), \ "=d,d" (dummy) \ : "a,a" (a<>(32-s)), \ "r,m" (b) \ : "%cc"); \ return result; \ } MAKECONSTDivScale(2) MAKECONSTDivScale(3) MAKECONSTDivScale(4) MAKECONSTDivScale(5) MAKECONSTDivScale(6) MAKECONSTDivScale(7) MAKECONSTDivScale(8) MAKECONSTDivScale(9) MAKECONSTDivScale(10) MAKECONSTDivScale(11) MAKECONSTDivScale(12) MAKECONSTDivScale(13) MAKECONSTDivScale(14) MAKECONSTDivScale(15) MAKECONSTDivScale(16) MAKECONSTDivScale(17) MAKECONSTDivScale(18) MAKECONSTDivScale(19) MAKECONSTDivScale(20) MAKECONSTDivScale(21) MAKECONSTDivScale(22) MAKECONSTDivScale(23) MAKECONSTDivScale(24) MAKECONSTDivScale(25) MAKECONSTDivScale(26) MAKECONSTDivScale(27) MAKECONSTDivScale(28) MAKECONSTDivScale(29) MAKECONSTDivScale(30) MAKECONSTDivScale(31) #undef MAKECONSTDivScale static inline SDWORD DivScale32 (SDWORD a, SDWORD b) { SDWORD result = 0, dummy; asm volatile ("idivl %3" :"+a,a" (result), "=d,d" (dummy) : "d,d" (a), "r,m" (b) : "%cc"); return result; } static inline void clearbuf (void *buff, int count, SDWORD clear) { int dummy1, dummy2; asm volatile ("rep stosl" :"=D" (dummy1), "=c" (dummy2) : "D" (buff), "c" (count), "a" (clear) ); } static inline void clearbufshort (void *buff, unsigned int count, WORD clear) { asm volatile ("shr $1,%%ecx\n\t" "rep stosl\n\t" "adc %%ecx,%%ecx\n\t" "rep stosw" :"=D" (buff), "=c" (count) :"D" (buff), "c" (count), "a" (clear|(clear<<16)) :"%cc"); } static inline SDWORD ksgn (SDWORD a) { SDWORD result, dummy; asm volatile ("add %0,%0\n\t" "sbb %1,%1\n\t" "cmp %0,%1\n\t" "adc $0,%1" :"=r" (dummy), "=r" (result) :"0" (a) :"%cc"); return result; }