Skip to content

Commit

Permalink
tweaked command line
Browse files Browse the repository at this point in the history
moved some inline asm to C-function to not interfere with optimizations
build with VS2011
  • Loading branch information
rainers committed Feb 24, 2012
1 parent e882ee2 commit 5afc486
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 87 deletions.
63 changes: 22 additions & 41 deletions src/root/longdouble.c
Expand Up @@ -23,12 +23,6 @@ extern "C"
{
// implemented in ldfpu.asm for _WIN64
int ld_initfpu(int bits, int mask);
double ld_read(longdouble* ld);
long long ld_readll(longdouble* ld);
unsigned long long ld_readull(longdouble* ld);
void ld_set(longdouble* ld, double d);
void ld_setll(longdouble* ld, long long d);
void ld_setull(longdouble* ld, unsigned long long d);
void ld_expl(longdouble* ld, int exp);
longdouble ld_add(longdouble ld1, longdouble ld2);
longdouble ld_sub(longdouble ld1, longdouble ld2);
Expand Down Expand Up @@ -61,24 +55,25 @@ bool initFPU()
}
static bool doInitFPU = initFPU();

double longdouble::readd()
#ifndef _WIN64
extern "C"
{

double ld_read(const longdouble* pthis)
{
#ifdef _WIN64
return ld_read(this);
#else
longdouble* pthis = this;
double res;
__asm
{
mov eax, pthis
fld tbyte ptr [eax]
fstp res
}
// return double in FP register
#endif
return res;
}
long long longdouble::readll()
long long ld_readll(const longdouble* pthis)
{
#if 1
return readull();
return ld_readull(pthis);
#elif defined _WIN64
return ld_readll(this);
#else
Expand All @@ -94,26 +89,24 @@ long long longdouble::readll()
#endif
}

unsigned long long longdouble::readull()
unsigned long long ld_readull(const longdouble* pthis)
{
#if 1
// somehow the FPU does not respect the CHOP mode of the rounding control
// in 64-bit mode
// so we roll our own conversion (it also allows the usual C wrap-around
// instead of the "invalid value" created by the FPU)
int expo = exponent - 0x3fff;
int expo = pthis->exponent - 0x3fff;
unsigned long long u;
if(expo < 0 || expo > 127)
return 0;
if(expo < 64)
u = mantissa >> (63 - expo);
u = pthis->mantissa >> (63 - expo);
else
u = mantissa << (expo - 63);
if(sign)
u = pthis->mantissa << (expo - 63);
if(pthis->sign)
u = ~u + 1;
return u;
#elif defined _WIN64
return ld_readull(this);
#else
longdouble* pthis = this;
long long res; // cannot use unsigned, VC will not generate "fistp qword"
Expand All @@ -133,41 +126,27 @@ unsigned long long longdouble::readull()
#endif
}

void longdouble::setd(double d)
void ld_set(longdouble* pthis, double d)
{
#ifdef _WIN64
return ld_set(this, d);
#else
longdouble* pthis = this;
__asm
{
mov eax, pthis
fld d
fstp tbyte ptr [eax]
}
#endif
}
void longdouble::setll(long long d)
void ld_setll(longdouble* pthis, long long d)
{
#ifdef _WIN64
return ld_setll(this, d);
#else
longdouble* pthis = this;
__asm
{
fild qword ptr d
mov eax, pthis
fstp tbyte ptr [eax]
}
#endif
}
void longdouble::setull(unsigned long long d)
void ld_setull(longdouble* pthis, unsigned long long d)
{
#ifdef _WIN64
return ld_setull(this, d);
#else
d ^= (1LL << 63);
longdouble* pthis = this;
longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 };
__asm
{
Expand All @@ -177,9 +156,11 @@ void longdouble::setull(unsigned long long d)
mov eax, pthis
fstp tbyte ptr [eax]
}
#endif
}

} // extern "C"
#endif // !_WIN64

longdouble ldexpl(longdouble ld, int exp)
{
#ifdef _WIN64
Expand Down Expand Up @@ -539,7 +520,7 @@ int ld_sprint(char* str, int fmt, longdouble x)
if(fmt != 'a' && fmt != 'A')
{
char format[] = { '%', fmt, 0 };
return sprintf(str, format, x.readd());
return sprintf(str, format, ld_read(&x));
}

unsigned short exp = x.exponent;
Expand Down
92 changes: 49 additions & 43 deletions src/root/longdouble.h
Expand Up @@ -46,6 +46,19 @@ inline int ld_sprint(char* str, int fmt, longdouble x)
#include <float.h>
#include <limits>

struct longdouble;

extern "C"
{
// implemented in ldfpu.asm for _WIN64
double ld_read(const longdouble* ld);
long long ld_readll(const longdouble* ld);
unsigned long long ld_readull(const longdouble* ld);
void ld_set(longdouble* ld, double d);
void ld_setll(longdouble* ld, long long d);
void ld_setull(longdouble* ld, unsigned long long d);
}

struct longdouble
{
unsigned long long mantissa;
Expand All @@ -56,49 +69,42 @@ struct longdouble
// no constructor to be able to use this class in a union
// use ldouble() to explicitely create a longdouble value

double readd();
long long readll();
unsigned long long readull();
void setd(double d);
void setll(long long d);
void setull(unsigned long long d);

template<typename T> longdouble& operator=(T x) { set(x); return *this; }

void set(longdouble ld) { mantissa = ld.mantissa; exponent = ld.exponent; sign = ld.sign; }

// we need to list all basic types to avoid ambiguities
void set(float d) { setd(d); }
void set(double d) { setd(d); }
void set(long double d) { setd(d); }

void set(signed char d) { setd(d); }
void set(short d) { setd(d); }
void set(int d) { setd(d); }
void set(long d) { setd(d); }
void set(long long d) { setll(d); }

void set(unsigned char d) { setd(d); }
void set(unsigned short d) { setd(d); }
void set(unsigned int d) { setd(d); }
void set(unsigned long d) { setd(d); }
void set(unsigned long long d) { setull(d); }
void set(bool d) { setd(d); }
void set(float d) { ld_set(this, d); }
void set(double d) { ld_set(this, d); }
void set(long double d) { ld_set(this, d); }

void set(signed char d) { ld_set(this, d); }
void set(short d) { ld_set(this, d); }
void set(int d) { ld_set(this, d); }
void set(long d) { ld_set(this, d); }
void set(long long d) { ld_setll(this, d); }

void set(unsigned char d) { ld_set(this, d); }
void set(unsigned short d) { ld_set(this, d); }
void set(unsigned int d) { ld_set(this, d); }
void set(unsigned long d) { ld_set(this, d); }
void set(unsigned long long d) { ld_setull(this, d); }
void set(bool d) { ld_set(this, d); }

operator float () { return readd(); }
operator double () { return readd(); }

operator signed char () { return readd(); }
operator short () { return readd(); }
operator int () { return readd(); }
operator long () { return readd(); }
operator long long () { return readll(); }

operator unsigned char () { return readd(); }
operator unsigned short () { return readd(); }
operator unsigned int () { return readd(); }
operator unsigned long () { return readd(); }
operator unsigned long long() { return readull(); }
operator float () { return ld_read(this); }
operator double () { return ld_read(this); }

operator signed char () { return ld_read(this); }
operator short () { return ld_read(this); }
operator int () { return ld_read(this); }
operator long () { return ld_read(this); }
operator long long () { return ld_readll(this); }

operator unsigned char () { return ld_read(this); }
operator unsigned short () { return ld_read(this); }
operator unsigned int () { return ld_read(this); }
operator unsigned long () { return ld_read(this); }
operator unsigned long long() { return ld_readull(this); }
operator bool () { return mantissa != 0 || exponent != 0; } // correct?
};

Expand Down Expand Up @@ -234,12 +240,12 @@ template<> class _CRTIMP2_PURE std::numeric_limits<longdouble>
_STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP);
};

_STCONSDEF(numeric_limits<longdouble>, int, digits)
_STCONSDEF(numeric_limits<longdouble>, int, digits10)
_STCONSDEF(numeric_limits<longdouble>, int, max_exponent)
_STCONSDEF(numeric_limits<longdouble>, int, max_exponent10)
_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)
//_STCONSDEF(numeric_limits<longdouble>, int, digits)
//_STCONSDEF(numeric_limits<longdouble>, int, digits10)
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent)
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent10)
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)

int ld_sprint(char* str, int fmt, longdouble x);

Expand Down
3 changes: 3 additions & 0 deletions src/vcbuild/builddmd.bat
Expand Up @@ -4,6 +4,9 @@ rem vcbuild\builddmd.bat
rem
rem Make sure that you do not have cl.exe from the dmc compiler
rem in your path!
rem
rem "make" should be the Digital Mars make, this can be found
rem if dmd's bin folder is in the path

set DEBUG=/Zi
if "%1" == "release" set DEBUG=/O2
Expand Down
7 changes: 4 additions & 3 deletions src/vcbuild/dmc_cl.bat
@@ -1,7 +1,8 @@
@echo off
rem echo called with: %*
set def=/DLITTLE_ENDIAN=1 /D__pascal= /D_M_I86=1
set copt=
rem copt defaults to linker options
set copt=/nologo /link /LARGEADDRESSAWARE
set cmd=
:next
if "%1" == "" goto done
Expand All @@ -15,7 +16,7 @@ if "%opt:~-2%" == ".c" goto isC
if "%opt:~-4%" == ".obj" goto add
set opt=%opt%.c
:isC
set copt=/TP /Ivcbuild /Iroot /nologo /EHsc %def%
set copt=/TP /Ivcbuild /Iroot /nologo /EHsc /Zp1 %def%
goto add

:opt
Expand All @@ -40,4 +41,4 @@ goto next

:done
rem echo cl %copt% %cmd%
cl %copt% %cmd%
cl %cmd% %copt%
1 change: 1 addition & 0 deletions src/vcbuild/warnings.h
Expand Up @@ -15,6 +15,7 @@
#pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning)
#pragma warning(disable:4390) // ';' : empty controlled statement found; is this the intent?
#pragma warning(disable:4702) // unreachable code
#pragma warning(disable:4703) // potentially uninitialized local pointer variable 'm' used

#ifdef _WIN64
#pragma warning(disable:4366) // The result of the unary '&' operator may be unaligned
Expand Down

0 comments on commit 5afc486

Please sign in to comment.