From a71612319ecdb0d0f06c01331174f329b031ea14 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 27 Aug 2010 23:36:25 -0700 Subject: [PATCH] c: Fix denormal handling Turns out the previous macro was using a gcc extension. MSVC didn't like that. --- orc/opcodes.h | 40 ++++---- orc/orcemulateopcodes.c | 216 ++++++++++++++++++++++++++++++++++------- orc/orcfunctions.c | 16 +--- orc/orcprogram-c.c | 250 +++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 418 insertions(+), 104 deletions(-) diff --git a/orc/opcodes.h b/orc/opcodes.h index 821404c..f8ec426 100644 --- a/orc/opcodes.h +++ b/orc/opcodes.h @@ -125,28 +125,20 @@ UNARY_UW(swapw, "ORC_SWAP_W(%s)") UNARY_UL(swapl, "ORC_SWAP_L(%s)") UNARY_UQ(swapq, "ORC_SWAP_Q(%s)") -BINARY_F(addf, "ORC_DENORMAL(ORC_DENORMAL(%s) + ORC_DENORMAL(%s))") -BINARY_F(subf, "ORC_DENORMAL(ORC_DENORMAL(%s) - ORC_DENORMAL(%s))") -BINARY_F(mulf, "ORC_DENORMAL(ORC_DENORMAL(%s) * ORC_DENORMAL(%s))") -BINARY_F(divf, "ORC_DENORMAL(ORC_DENORMAL(%s) / ORC_DENORMAL(%s))") -UNARY_F(sqrtf, "sqrt(ORC_DENORMAL(%s))") -BINARY_F(maxf, "ORC_MAXF(ORC_DENORMAL(%s),ORC_DENORMAL(%s))") -BINARY_F(minf, "ORC_MINF(ORC_DENORMAL(%s),ORC_DENORMAL(%s))") -BINARY_FL(cmpeqf, "(ORC_DENORMAL(%s) == ORC_DENORMAL(%s)) ? (~0) : 0") -BINARY_FL(cmpltf, "(ORC_DENORMAL(%s) < ORC_DENORMAL(%s)) ? (~0) : 0") -BINARY_FL(cmplef, "(ORC_DENORMAL(%s) <= ORC_DENORMAL(%s)) ? (~0) : 0") -UNARY_LF(convlf, "%s") +BINARY_F(addf, "%s + %s") +BINARY_F(subf, "%s - %s") +BINARY_F(mulf, "%s * %s") +BINARY_F(divf, "%s / %s") +UNARY_F(sqrtf, "sqrt(%s)") +BINARY_FL(cmpeqf, "(%s == %s) ? (~0) : 0") +BINARY_FL(cmpltf, "(%s < %s) ? (~0) : 0") +BINARY_FL(cmplef, "(%s <= %s) ? (~0) : 0") -BINARY_D(addd, "ORC_DENORMAL_D(ORC_DENORMAL_D(%s) + ORC_DENORMAL_D(%s))") -BINARY_D(subd, "ORC_DENORMAL_D(ORC_DENORMAL_D(%s) - ORC_DENORMAL_D(%s))") -BINARY_D(muld, "ORC_DENORMAL_D(ORC_DENORMAL_D(%s) * ORC_DENORMAL_D(%s))") -BINARY_D(divd, "ORC_DENORMAL_D(ORC_DENORMAL_D(%s) / ORC_DENORMAL_D(%s))") -UNARY_D(sqrtd, "sqrt(ORC_DENORMAL_D(%s))") -BINARY_D(maxd, "ORC_MAXD(ORC_DENORMAL_D(%s),ORC_DENORMAL_D(%s))") -BINARY_D(mind, "ORC_MIND(ORC_DENORMAL_D(%s),ORC_DENORMAL_D(%s))") -BINARY_DQ(cmpeqd, "(ORC_DENORMAL_D(%s) == ORC_DENORMAL_D(%s)) ? (~0ULL) : 0") -BINARY_DQ(cmpltd, "(ORC_DENORMAL_D(%s) < ORC_DENORMAL_D(%s)) ? (~0ULL) : 0") -BINARY_DQ(cmpled, "(ORC_DENORMAL_D(%s) <= ORC_DENORMAL_D(%s)) ? (~0ULL) : 0") -UNARY_LD(convld, "%s") -UNARY_DF(convdf, "ORC_DENORMAL ((float) %s)") -UNARY_FD(convfd, "ORC_DENORMAL (%s)") +BINARY_D(addd, "%s + %s") +BINARY_D(subd, "%s - %s") +BINARY_D(muld, "%s * %s") +BINARY_D(divd, "%s / %s") +UNARY_D(sqrtd, "sqrt(%s)") +BINARY_DQ(cmpeqd, "(%s == %s) ? (~0ULL) : 0") +BINARY_DQ(cmpltd, "(%s < %s) ? (~0ULL) : 0") +BINARY_DQ(cmpled, "(%s <= %s) ? (~0ULL) : 0") diff --git a/orc/orcemulateopcodes.c b/orc/orcemulateopcodes.c index 8a89ca8..5288439 100644 --- a/orc/orcemulateopcodes.c +++ b/orc/orcemulateopcodes.c @@ -35,18 +35,10 @@ #define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24)) #define ORC_SWAP_Q(x) ((((x)&0xffULL)<<56) | (((x)&0xff00ULL)<<40) | (((x)&0xff0000ULL)<<24) | (((x)&0xff000000ULL)<<8) | (((x)&0xff00000000ULL)>>8) | (((x)&0xff0000000000ULL)>>24) | (((x)&0xff000000000000ULL)>>40) | (((x)&0xff00000000000000ULL)>>56)) #define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset))) -#define ORC_RECAST_INT(x) (((orc_union32)(x)).i) -#define ORC_RECAST_FLOAT(x) (((orc_union32)(orc_int32)(x)).f) -#define ORC_DENORMAL(x) ORC_RECAST_FLOAT(ORC_RECAST_INT(x) & (((ORC_RECAST_INT(x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) -#define ORC_ISNAN(x) (((ORC_RECAST_INT(x)&0x7f800000) == 0x7f800000) && ((ORC_RECAST_INT(x)&0x007fffff) != 0)) -#define ORC_MINF(a,b) (ORC_ISNAN(a) ? a : ORC_ISNAN(b) ? b : ((a)<(b)) ? (a) : (b)) -#define ORC_MAXF(a,b) (ORC_ISNAN(a) ? a : ORC_ISNAN(b) ? b : ((a)>(b)) ? (a) : (b)) -#define ORC_RECAST_INT64(x) (((orc_union64)(x)).i) -#define ORC_RECAST_DOUBLE(x) (((orc_union64)(orc_int64)(x)).f) -#define ORC_DENORMAL_D(x) ORC_RECAST_DOUBLE(ORC_RECAST_INT64(x) & (((ORC_RECAST_INT64(x)&0x7ff0000000000000ULL) == 0) ? 0xfff0000000000000ULL : 0xffffffffffffffffULL)) -#define ORC_ISNAN_D(x) (((ORC_RECAST_INT64(x)&0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) && ((ORC_RECAST_INT64(x)&0x000fffffffffffffULL) != 0)) -#define ORC_MIND(a,b) (ORC_ISNAN_D(a) ? a : ORC_ISNAN_D(b) ? b : ((a)<(b)) ? (a) : (b)) -#define ORC_MAXD(a,b) (ORC_ISNAN_D(a) ? a : ORC_ISNAN_D(b) ? b : ((a)>(b)) ? (a) : (b)) +#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) +#define ORC_ISNAN(x) ((((x)&0x7f800000) == 0x7f800000) && (((x)&0x007fffff) != 0)) +#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&0x7ff0000000000000ULL) == 0) ? 0xfff0000000000000ULL : 0xffffffffffffffffULL)) +#define ORC_ISNAN_DOUBLE(x) ((((x)&0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) && (((x)&0x000fffffffffffffULL) != 0)) #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define ORC_RESTRICT restrict #elif defined(__GNUC__) && __GNUC__ >= 4 @@ -3832,7 +3824,15 @@ emulate_addf (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: addf */ - var34.f = ORC_DENORMAL(ORC_DENORMAL(var32.f) + ORC_DENORMAL(var33.f)); + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + _dest1.f = _src1.f + _src2.f; + var34.i = ORC_DENORMAL(_dest1.i); + } /* 3: storel */ ptr0[i] = var34; } @@ -3860,7 +3860,15 @@ emulate_subf (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: subf */ - var34.f = ORC_DENORMAL(ORC_DENORMAL(var32.f) - ORC_DENORMAL(var33.f)); + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + _dest1.f = _src1.f - _src2.f; + var34.i = ORC_DENORMAL(_dest1.i); + } /* 3: storel */ ptr0[i] = var34; } @@ -3888,7 +3896,15 @@ emulate_mulf (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: mulf */ - var34.f = ORC_DENORMAL(ORC_DENORMAL(var32.f) * ORC_DENORMAL(var33.f)); + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + _dest1.f = _src1.f * _src2.f; + var34.i = ORC_DENORMAL(_dest1.i); + } /* 3: storel */ ptr0[i] = var34; } @@ -3916,7 +3932,15 @@ emulate_divf (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: divf */ - var34.f = ORC_DENORMAL(ORC_DENORMAL(var32.f) / ORC_DENORMAL(var33.f)); + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + _dest1.f = _src1.f / _src2.f; + var34.i = ORC_DENORMAL(_dest1.i); + } /* 3: storel */ ptr0[i] = var34; } @@ -3939,7 +3963,13 @@ emulate_sqrtf (OrcOpcodeExecutor *ex, int offset, int n) /* 0: loadl */ var32 = ptr4[i]; /* 1: sqrtf */ - var33.f = sqrt(ORC_DENORMAL(var32.f)); + { + orc_union32 _src1; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL(var32.i); + _dest1.f = sqrt(_src1.f); + var33.i = ORC_DENORMAL(_dest1.i); + } /* 2: storel */ ptr0[i] = var33; } @@ -3967,7 +3997,15 @@ emulate_maxf (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: maxf */ - var34.f = ORC_MAXF(ORC_DENORMAL(var32.f),ORC_DENORMAL(var33.f)); + { + orc_union32 _src1; + orc_union32 _src2; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + if (ORC_ISNAN(_src1.i)) var34.i = _src1.i; + else if (ORC_ISNAN(_src2.i)) var34.i = _src2.i; + else var34.i = (_src1.f > _src2.f) ? _src1.i : _src2.i; + } /* 3: storel */ ptr0[i] = var34; } @@ -3995,7 +4033,15 @@ emulate_minf (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: minf */ - var34.f = ORC_MINF(ORC_DENORMAL(var32.f),ORC_DENORMAL(var33.f)); + { + orc_union32 _src1; + orc_union32 _src2; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + if (ORC_ISNAN(_src1.i)) var34.i = _src1.i; + else if (ORC_ISNAN(_src2.i)) var34.i = _src2.i; + else var34.i = (_src1.f < _src2.f) ? _src1.i : _src2.i; + } /* 3: storel */ ptr0[i] = var34; } @@ -4023,7 +4069,13 @@ emulate_cmpeqf (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: cmpeqf */ - var34.i = (ORC_DENORMAL(var32.f) == ORC_DENORMAL(var33.f)) ? (~0) : 0; + { + orc_union32 _src1; + orc_union32 _src2; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + var34.i = (_src1.f == _src2.f) ? (~0) : 0; + } /* 3: storel */ ptr0[i] = var34; } @@ -4051,7 +4103,13 @@ emulate_cmpltf (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: cmpltf */ - var34.i = (ORC_DENORMAL(var32.f) < ORC_DENORMAL(var33.f)) ? (~0) : 0; + { + orc_union32 _src1; + orc_union32 _src2; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + var34.i = (_src1.f < _src2.f) ? (~0) : 0; + } /* 3: storel */ ptr0[i] = var34; } @@ -4079,7 +4137,13 @@ emulate_cmplef (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadl */ var33 = ptr5[i]; /* 2: cmplef */ - var34.i = (ORC_DENORMAL(var32.f) <= ORC_DENORMAL(var33.f)) ? (~0) : 0; + { + orc_union32 _src1; + orc_union32 _src2; + _src1.i = ORC_DENORMAL(var32.i); + _src2.i = ORC_DENORMAL(var33.i); + var34.i = (_src1.f <= _src2.f) ? (~0) : 0; + } /* 3: storel */ ptr0[i] = var34; } @@ -4130,7 +4194,7 @@ emulate_convlf (OrcOpcodeExecutor *ex, int offset, int n) /* 0: loadl */ var32 = ptr4[i]; /* 1: convlf */ - var33.f = var32.i; + var33.f = var32.i; /* 2: storel */ ptr0[i] = var33; } @@ -4158,7 +4222,15 @@ emulate_addd (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: addd */ - var34.f = ORC_DENORMAL_D(ORC_DENORMAL_D(var32.f) + ORC_DENORMAL_D(var33.f)); + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + _dest1.f = _src1.f + _src2.f; + var34.i = ORC_DENORMAL_DOUBLE(_dest1.i); + } /* 3: storeq */ ptr0[i] = var34; } @@ -4186,7 +4258,15 @@ emulate_subd (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: subd */ - var34.f = ORC_DENORMAL_D(ORC_DENORMAL_D(var32.f) - ORC_DENORMAL_D(var33.f)); + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + _dest1.f = _src1.f - _src2.f; + var34.i = ORC_DENORMAL_DOUBLE(_dest1.i); + } /* 3: storeq */ ptr0[i] = var34; } @@ -4214,7 +4294,15 @@ emulate_muld (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: muld */ - var34.f = ORC_DENORMAL_D(ORC_DENORMAL_D(var32.f) * ORC_DENORMAL_D(var33.f)); + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + _dest1.f = _src1.f * _src2.f; + var34.i = ORC_DENORMAL_DOUBLE(_dest1.i); + } /* 3: storeq */ ptr0[i] = var34; } @@ -4242,7 +4330,15 @@ emulate_divd (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: divd */ - var34.f = ORC_DENORMAL_D(ORC_DENORMAL_D(var32.f) / ORC_DENORMAL_D(var33.f)); + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + _dest1.f = _src1.f / _src2.f; + var34.i = ORC_DENORMAL_DOUBLE(_dest1.i); + } /* 3: storeq */ ptr0[i] = var34; } @@ -4265,7 +4361,13 @@ emulate_sqrtd (OrcOpcodeExecutor *ex, int offset, int n) /* 0: loadq */ var32 = ptr4[i]; /* 1: sqrtd */ - var33.f = sqrt(ORC_DENORMAL_D(var32.f)); + { + orc_union64 _src1; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _dest1.f = sqrt(_src1.f); + var33.i = ORC_DENORMAL_DOUBLE(_dest1.i); + } /* 2: storeq */ ptr0[i] = var33; } @@ -4293,7 +4395,15 @@ emulate_maxd (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: maxd */ - var34.f = ORC_MAXD(ORC_DENORMAL_D(var32.f),ORC_DENORMAL_D(var33.f)); + { + orc_union64 _src1; + orc_union64 _src2; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + if (ORC_ISNAN_DOUBLE(_src1.i)) var34.i = _src1.i; + else if (ORC_ISNAN_DOUBLE(_src2.i)) var34.i = _src2.i; + else var34.i = (_src1.f > _src2.f) ? _src1.i : _src2.i; + } /* 3: storeq */ ptr0[i] = var34; } @@ -4321,7 +4431,15 @@ emulate_mind (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: mind */ - var34.f = ORC_MIND(ORC_DENORMAL_D(var32.f),ORC_DENORMAL_D(var33.f)); + { + orc_union64 _src1; + orc_union64 _src2; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + if (ORC_ISNAN_DOUBLE(_src1.i)) var34.i = _src1.i; + else if (ORC_ISNAN_DOUBLE(_src2.i)) var34.i = _src2.i; + else var34.i = (_src1.f < _src2.f) ? _src1.i : _src2.i; + } /* 3: storeq */ ptr0[i] = var34; } @@ -4349,7 +4467,13 @@ emulate_cmpeqd (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: cmpeqd */ - var34.i = (ORC_DENORMAL_D(var32.f) == ORC_DENORMAL_D(var33.f)) ? (~0ULL) : 0; + { + orc_union64 _src1; + orc_union64 _src2; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + var34.i = (_src1.f == _src2.f) ? (~0ULL) : 0; + } /* 3: storeq */ ptr0[i] = var34; } @@ -4377,7 +4501,13 @@ emulate_cmpltd (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: cmpltd */ - var34.i = (ORC_DENORMAL_D(var32.f) < ORC_DENORMAL_D(var33.f)) ? (~0ULL) : 0; + { + orc_union64 _src1; + orc_union64 _src2; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + var34.i = (_src1.f < _src2.f) ? (~0ULL) : 0; + } /* 3: storeq */ ptr0[i] = var34; } @@ -4405,7 +4535,13 @@ emulate_cmpled (OrcOpcodeExecutor *ex, int offset, int n) /* 1: loadq */ var33 = ptr5[i]; /* 2: cmpled */ - var34.i = (ORC_DENORMAL_D(var32.f) <= ORC_DENORMAL_D(var33.f)) ? (~0ULL) : 0; + { + orc_union64 _src1; + orc_union64 _src2; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + _src2.i = ORC_DENORMAL_DOUBLE(var33.i); + var34.i = (_src1.f <= _src2.f) ? (~0ULL) : 0; + } /* 3: storeq */ ptr0[i] = var34; } @@ -4456,7 +4592,7 @@ emulate_convld (OrcOpcodeExecutor *ex, int offset, int n) /* 0: loadl */ var32 = ptr4[i]; /* 1: convld */ - var33.f = var32.i; + var33.f = var32.i; /* 2: storeq */ ptr0[i] = var33; } @@ -4479,7 +4615,11 @@ emulate_convfd (OrcOpcodeExecutor *ex, int offset, int n) /* 0: loadl */ var32 = ptr4[i]; /* 1: convfd */ - var33.f = ORC_DENORMAL (var32.f); + { + orc_union32 _src1; + _src1.i = ORC_DENORMAL(var32.i); + var33.f = _src1.f; + } /* 2: storeq */ ptr0[i] = var33; } @@ -4502,7 +4642,11 @@ emulate_convdf (OrcOpcodeExecutor *ex, int offset, int n) /* 0: loadq */ var32 = ptr4[i]; /* 1: convdf */ - var33.f = ORC_DENORMAL ((float) var32.f); + { + orc_union64 _src1; + _src1.i = ORC_DENORMAL_DOUBLE(var32.i); + var33.f = _src1.f; + } /* 2: storel */ ptr0[i] = var33; } diff --git a/orc/orcfunctions.c b/orc/orcfunctions.c index 43ae9a2..a9dbd59 100644 --- a/orc/orcfunctions.c +++ b/orc/orcfunctions.c @@ -81,18 +81,10 @@ void orc_memset (void * d1, int p1, int n); #define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24)) #define ORC_SWAP_Q(x) ((((x)&0xffULL)<<56) | (((x)&0xff00ULL)<<40) | (((x)&0xff0000ULL)<<24) | (((x)&0xff000000ULL)<<8) | (((x)&0xff00000000ULL)>>8) | (((x)&0xff0000000000ULL)>>24) | (((x)&0xff000000000000ULL)>>40) | (((x)&0xff00000000000000ULL)>>56)) #define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset))) -#define ORC_RECAST_INT(x) (((orc_union32)(x)).i) -#define ORC_RECAST_FLOAT(x) (((orc_union32)(orc_int32)(x)).f) -#define ORC_DENORMAL(x) ORC_RECAST_FLOAT(ORC_RECAST_INT(x) & (((ORC_RECAST_INT(x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) -#define ORC_ISNAN(x) (((ORC_RECAST_INT(x)&0x7f800000) == 0x7f800000) && ((ORC_RECAST_INT(x)&0x007fffff) != 0)) -#define ORC_MINF(a,b) (ORC_ISNAN(a) ? a : ORC_ISNAN(b) ? b : ((a)<(b)) ? (a) : (b)) -#define ORC_MAXF(a,b) (ORC_ISNAN(a) ? a : ORC_ISNAN(b) ? b : ((a)>(b)) ? (a) : (b)) -#define ORC_RECAST_INT64(x) (((orc_union64)(x)).i) -#define ORC_RECAST_DOUBLE(x) (((orc_union64)(orc_int64)(x)).f) -#define ORC_DENORMAL_D(x) ORC_RECAST_DOUBLE(ORC_RECAST_INT64(x) & (((ORC_RECAST_INT64(x)&0x7ff0000000000000ULL) == 0) ? 0xfff0000000000000ULL : 0xffffffffffffffffULL)) -#define ORC_ISNAN_D(x) (((ORC_RECAST_INT64(x)&0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) && ((ORC_RECAST_INT64(x)&0x000fffffffffffffULL) != 0)) -#define ORC_MIND(a,b) (ORC_ISNAN_D(a) ? a : ORC_ISNAN_D(b) ? b : ((a)<(b)) ? (a) : (b)) -#define ORC_MAXD(a,b) (ORC_ISNAN_D(a) ? a : ORC_ISNAN_D(b) ? b : ((a)>(b)) ? (a) : (b)) +#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) +#define ORC_ISNAN(x) ((((x)&0x7f800000) == 0x7f800000) && (((x)&0x007fffff) != 0)) +#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&0x7ff0000000000000ULL) == 0) ? 0xfff0000000000000ULL : 0xffffffffffffffffULL)) +#define ORC_ISNAN_DOUBLE(x) ((((x)&0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) && (((x)&0x000fffffffffffffULL) != 0)) #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define ORC_RESTRICT restrict #elif defined(__GNUC__) && __GNUC__ >= 4 diff --git a/orc/orcprogram-c.c b/orc/orcprogram-c.c index 7ac4b42..f2519f0 100644 --- a/orc/orcprogram-c.c +++ b/orc/orcprogram-c.c @@ -103,18 +103,10 @@ orc_target_c_get_asm_preamble (void) "#define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24))\n" "#define ORC_SWAP_Q(x) ((((x)&0xffULL)<<56) | (((x)&0xff00ULL)<<40) | (((x)&0xff0000ULL)<<24) | (((x)&0xff000000ULL)<<8) | (((x)&0xff00000000ULL)>>8) | (((x)&0xff0000000000ULL)>>24) | (((x)&0xff000000000000ULL)>>40) | (((x)&0xff00000000000000ULL)>>56))\n" "#define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset)))\n" - "#define ORC_RECAST_INT(x) (((orc_union32)(x)).i)\n" - "#define ORC_RECAST_FLOAT(x) (((orc_union32)(orc_int32)(x)).f)\n" - "#define ORC_DENORMAL(x) ORC_RECAST_FLOAT(ORC_RECAST_INT(x) & (((ORC_RECAST_INT(x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff))\n" - "#define ORC_ISNAN(x) (((ORC_RECAST_INT(x)&0x7f800000) == 0x7f800000) && ((ORC_RECAST_INT(x)&0x007fffff) != 0))\n" - "#define ORC_MINF(a,b) (ORC_ISNAN(a) ? a : ORC_ISNAN(b) ? b : ((a)<(b)) ? (a) : (b))\n" - "#define ORC_MAXF(a,b) (ORC_ISNAN(a) ? a : ORC_ISNAN(b) ? b : ((a)>(b)) ? (a) : (b))\n" - "#define ORC_RECAST_INT64(x) (((orc_union64)(x)).i)\n" - "#define ORC_RECAST_DOUBLE(x) (((orc_union64)(orc_int64)(x)).f)\n" - "#define ORC_DENORMAL_D(x) ORC_RECAST_DOUBLE(ORC_RECAST_INT64(x) & (((ORC_RECAST_INT64(x)&0x7ff0000000000000ULL) == 0) ? 0xfff0000000000000ULL : 0xffffffffffffffffULL))\n" - "#define ORC_ISNAN_D(x) (((ORC_RECAST_INT64(x)&0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) && ((ORC_RECAST_INT64(x)&0x000fffffffffffffULL) != 0))\n" - "#define ORC_MIND(a,b) (ORC_ISNAN_D(a) ? a : ORC_ISNAN_D(b) ? b : ((a)<(b)) ? (a) : (b))\n" - "#define ORC_MAXD(a,b) (ORC_ISNAN_D(a) ? a : ORC_ISNAN_D(b) ? b : ((a)>(b)) ? (a) : (b))\n" + "#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff))\n" + "#define ORC_ISNAN(x) ((((x)&0x7f800000) == 0x7f800000) && (((x)&0x007fffff) != 0))\n" + "#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&0x7ff0000000000000ULL) == 0) ? 0xfff0000000000000ULL : 0xffffffffffffffffULL))\n" + "#define ORC_ISNAN_DOUBLE(x) ((((x)&0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) && (((x)&0x000fffffffffffffULL) != 0))\n" "#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n" "#define ORC_RESTRICT restrict\n" "#elif defined(__GNUC__) && __GNUC__ >= 4\n" @@ -542,10 +534,16 @@ c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ { \ char dest[40], src1[40]; \ \ - c_get_name_float (dest, p, insn, insn->dest_args[0]); \ - c_get_name_float (src1, p, insn, insn->src_args[0]); \ + c_get_name_int (dest, p, insn, insn->dest_args[0]); \ + c_get_name_int (src1, p, insn, insn->src_args[0]); \ \ - ORC_ASM_CODE(p," %s = " op ";\n", dest, src1); \ + ORC_ASM_CODE(p, " {\n"); \ + ORC_ASM_CODE(p," orc_union32 _src1;\n"); \ + ORC_ASM_CODE(p," orc_union32 _dest1;\n"); \ + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL(%s);\n", src1); \ + ORC_ASM_CODE(p," _dest1.f = " op ";\n", "_src1.f"); \ + ORC_ASM_CODE(p," %s = ORC_DENORMAL(_dest1.i);\n", dest); \ + ORC_ASM_CODE(p, " }\n"); \ } #define BINARYF(name,op) \ @@ -554,11 +552,19 @@ c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ { \ char dest[40], src1[40], src2[40]; \ \ - c_get_name_float (dest, p, insn, insn->dest_args[0]); \ - c_get_name_float (src1, p, insn, insn->src_args[0]); \ - c_get_name_float (src2, p, insn, insn->src_args[1]); \ + c_get_name_int (dest, p, insn, insn->dest_args[0]); \ + c_get_name_int (src1, p, insn, insn->src_args[0]); \ + c_get_name_int (src2, p, insn, insn->src_args[1]); \ \ - ORC_ASM_CODE(p," %s = " op ";\n", dest, src1, src2); \ + ORC_ASM_CODE(p, " {\n"); \ + ORC_ASM_CODE(p," orc_union32 _src1;\n"); \ + ORC_ASM_CODE(p," orc_union32 _src2;\n"); \ + ORC_ASM_CODE(p," orc_union32 _dest1;\n"); \ + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL(%s);\n", src1); \ + ORC_ASM_CODE(p," _src2.i = ORC_DENORMAL(%s);\n", src2); \ + ORC_ASM_CODE(p," _dest1.f = " op ";\n", "_src1.f", "_src2.f"); \ + ORC_ASM_CODE(p," %s = ORC_DENORMAL(_dest1.i);\n", dest); \ + ORC_ASM_CODE(p, " }\n"); \ } #define BINARYFL(name,op) \ @@ -568,34 +574,74 @@ c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ char dest[40], src1[40], src2[40]; \ \ c_get_name_int (dest, p, insn, insn->dest_args[0]); \ - c_get_name_float (src1, p, insn, insn->src_args[0]); \ - c_get_name_float (src2, p, insn, insn->src_args[1]); \ + c_get_name_int (src1, p, insn, insn->src_args[0]); \ + c_get_name_int (src2, p, insn, insn->src_args[1]); \ \ - ORC_ASM_CODE(p," %s = " op ";\n", dest, src1, src2); \ + ORC_ASM_CODE(p, " {\n"); \ + ORC_ASM_CODE(p," orc_union32 _src1;\n"); \ + ORC_ASM_CODE(p," orc_union32 _src2;\n"); \ + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL(%s);\n", src1); \ + ORC_ASM_CODE(p," _src2.i = ORC_DENORMAL(%s);\n", src2); \ + ORC_ASM_CODE(p," %s = " op ";\n", dest, "_src1.f", "_src2.f"); \ + ORC_ASM_CODE(p, " }\n"); \ } -#define UNARYFL(name,op) \ +#define UNARYD(name,op) \ static void \ c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ { \ char dest[40], src1[40]; \ \ c_get_name_int (dest, p, insn, insn->dest_args[0]); \ - c_get_name_float (src1, p, insn, insn->src_args[0]); \ + c_get_name_int (src1, p, insn, insn->src_args[0]); \ \ - ORC_ASM_CODE(p," %s = " op ";\n", dest, src1); \ + ORC_ASM_CODE(p, " {\n"); \ + ORC_ASM_CODE(p," orc_union64 _src1;\n"); \ + ORC_ASM_CODE(p," orc_union64 _dest1;\n"); \ + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL_DOUBLE(%s);\n", src1); \ + ORC_ASM_CODE(p," _dest1.f = " op ";\n", "_src1.f"); \ + ORC_ASM_CODE(p," %s = ORC_DENORMAL_DOUBLE(_dest1.i);\n", dest); \ + ORC_ASM_CODE(p, " }\n"); \ } -#define UNARYLF(name,op) \ +#define BINARYD(name,op) \ static void \ c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ { \ - char dest[40], src1[40]; \ + char dest[40], src1[40], src2[40]; \ \ - c_get_name_float (dest, p, insn, insn->dest_args[0]); \ + c_get_name_int (dest, p, insn, insn->dest_args[0]); \ c_get_name_int (src1, p, insn, insn->src_args[0]); \ + c_get_name_int (src2, p, insn, insn->src_args[1]); \ \ - ORC_ASM_CODE(p," %s = " op ";\n", dest, src1); \ + ORC_ASM_CODE(p, " {\n"); \ + ORC_ASM_CODE(p," orc_union64 _src1;\n"); \ + ORC_ASM_CODE(p," orc_union64 _src2;\n"); \ + ORC_ASM_CODE(p," orc_union64 _dest1;\n"); \ + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL_DOUBLE(%s);\n", src1); \ + ORC_ASM_CODE(p," _src2.i = ORC_DENORMAL_DOUBLE(%s);\n", src2); \ + ORC_ASM_CODE(p," _dest1.f = " op ";\n", "_src1.f", "_src2.f"); \ + ORC_ASM_CODE(p," %s = ORC_DENORMAL_DOUBLE(_dest1.i);\n", dest); \ + ORC_ASM_CODE(p, " }\n"); \ +} + +#define BINARYDQ(name,op) \ +static void \ +c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ +{ \ + char dest[40], src1[40], src2[40]; \ +\ + c_get_name_int (dest, p, insn, insn->dest_args[0]); \ + c_get_name_int (src1, p, insn, insn->src_args[0]); \ + c_get_name_int (src2, p, insn, insn->src_args[1]); \ + \ + ORC_ASM_CODE(p, " {\n"); \ + ORC_ASM_CODE(p," orc_union64 _src1;\n"); \ + ORC_ASM_CODE(p," orc_union64 _src2;\n"); \ + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL_DOUBLE(%s);\n", src1); \ + ORC_ASM_CODE(p," _src2.i = ORC_DENORMAL_DOUBLE(%s);\n", src2); \ + ORC_ASM_CODE(p," %s = " op ";\n", dest, "_src1.f", "_src2.f"); \ + ORC_ASM_CODE(p, " }\n"); \ } #define BINARY_SB(a,b) BINARY(a,b) @@ -631,9 +677,9 @@ c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \ #define UNARY_FL(a,b) UNARYFL(a,b) #define UNARY_LF(a,b) UNARYLF(a,b) -#define BINARY_D(a,b) BINARYF(a,b) -#define BINARY_DQ(a,b) BINARYFL(a,b) -#define UNARY_D(a,b) UNARYF(a,b) +#define BINARY_D(a,b) BINARYD(a,b) +#define BINARY_DQ(a,b) BINARYDQ(a,b) +#define UNARY_D(a,b) UNARYD(a,b) #define UNARY_DL(a,b) UNARYFL(a,b) #define UNARY_LD(a,b) UNARYLF(a,b) #define UNARY_DF(a,b) UNARYF(a,b) @@ -1006,6 +1052,58 @@ c_rule_divluw (OrcCompiler *p, void *user, OrcInstruction *insn) } static void +c_rule_convlf (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + char dest[40], src1[40]; + + c_get_name_float (dest, p, insn, insn->dest_args[0]); + c_get_name_int (src1, p, insn, insn->src_args[0]); + + ORC_ASM_CODE(p," %s = %s;\n", dest, src1); +} + +static void +c_rule_convld (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + char dest[40], src1[40]; + + c_get_name_float (dest, p, insn, insn->dest_args[0]); + c_get_name_int (src1, p, insn, insn->src_args[0]); + + ORC_ASM_CODE(p," %s = %s;\n", dest, src1); +} + +static void +c_rule_convfd (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + char dest[40], src1[40]; + + c_get_name_float (dest, p, insn, insn->dest_args[0]); + c_get_name_int (src1, p, insn, insn->src_args[0]); + + ORC_ASM_CODE(p, " {\n"); + ORC_ASM_CODE(p," orc_union32 _src1;\n"); + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL(%s);\n", src1); + ORC_ASM_CODE(p," %s = _src1.f;\n", dest); + ORC_ASM_CODE(p, " }\n"); +} + +static void +c_rule_convdf (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + char dest[40], src1[40]; + + c_get_name_float (dest, p, insn, insn->dest_args[0]); + c_get_name_int (src1, p, insn, insn->src_args[0]); + + ORC_ASM_CODE(p, " {\n"); + ORC_ASM_CODE(p," orc_union64 _src1;\n"); + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL_DOUBLE(%s);\n", src1); + ORC_ASM_CODE(p," %s = _src1.f;\n", dest); + ORC_ASM_CODE(p, " }\n"); +} + +static void c_rule_convfl (OrcCompiler *p, void *user, OrcInstruction *insn) { char dest[40], src[40], src_i[40]; @@ -1039,6 +1137,86 @@ c_rule_convdl (OrcCompiler *p, void *user, OrcInstruction *insn) ORC_ASM_CODE(p, " }\n"); } +static void +c_rule_minf (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + char dest[40], src1[40], src2[40]; + + c_get_name_int (dest, p, insn, insn->dest_args[0]); + c_get_name_int (src1, p, insn, insn->src_args[0]); + c_get_name_int (src2, p, insn, insn->src_args[1]); + + ORC_ASM_CODE(p," {\n"); + ORC_ASM_CODE(p," orc_union32 _src1;\n"); + ORC_ASM_CODE(p," orc_union32 _src2;\n"); + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL(%s);\n", src1); + ORC_ASM_CODE(p," _src2.i = ORC_DENORMAL(%s);\n", src2); + ORC_ASM_CODE(p," if (ORC_ISNAN(_src1.i)) %s = _src1.i;\n", dest); + ORC_ASM_CODE(p," else if (ORC_ISNAN(_src2.i)) %s = _src2.i;\n", dest); + ORC_ASM_CODE(p," else %s = (_src1.f < _src2.f) ? _src1.i : _src2.i;\n", dest); + ORC_ASM_CODE(p," }\n"); +} + +static void +c_rule_maxf (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + char dest[40], src1[40], src2[40]; + + c_get_name_int (dest, p, insn, insn->dest_args[0]); + c_get_name_int (src1, p, insn, insn->src_args[0]); + c_get_name_int (src2, p, insn, insn->src_args[1]); + + ORC_ASM_CODE(p," {\n"); + ORC_ASM_CODE(p," orc_union32 _src1;\n"); + ORC_ASM_CODE(p," orc_union32 _src2;\n"); + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL(%s);\n", src1); + ORC_ASM_CODE(p," _src2.i = ORC_DENORMAL(%s);\n", src2); + ORC_ASM_CODE(p," if (ORC_ISNAN(_src1.i)) %s = _src1.i;\n", dest); + ORC_ASM_CODE(p," else if (ORC_ISNAN(_src2.i)) %s = _src2.i;\n", dest); + ORC_ASM_CODE(p," else %s = (_src1.f > _src2.f) ? _src1.i : _src2.i;\n", dest); + ORC_ASM_CODE(p," }\n"); +} + +static void +c_rule_mind (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + char dest[40], src1[40], src2[40]; + + c_get_name_int (dest, p, insn, insn->dest_args[0]); + c_get_name_int (src1, p, insn, insn->src_args[0]); + c_get_name_int (src2, p, insn, insn->src_args[1]); + + ORC_ASM_CODE(p," {\n"); + ORC_ASM_CODE(p," orc_union64 _src1;\n"); + ORC_ASM_CODE(p," orc_union64 _src2;\n"); + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL_DOUBLE(%s);\n", src1); + ORC_ASM_CODE(p," _src2.i = ORC_DENORMAL_DOUBLE(%s);\n", src2); + ORC_ASM_CODE(p," if (ORC_ISNAN_DOUBLE(_src1.i)) %s = _src1.i;\n", dest); + ORC_ASM_CODE(p," else if (ORC_ISNAN_DOUBLE(_src2.i)) %s = _src2.i;\n", dest); + ORC_ASM_CODE(p," else %s = (_src1.f < _src2.f) ? _src1.i : _src2.i;\n", dest); + ORC_ASM_CODE(p," }\n"); +} + +static void +c_rule_maxd (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + char dest[40], src1[40], src2[40]; + + c_get_name_int (dest, p, insn, insn->dest_args[0]); + c_get_name_int (src1, p, insn, insn->src_args[0]); + c_get_name_int (src2, p, insn, insn->src_args[1]); + + ORC_ASM_CODE(p," {\n"); + ORC_ASM_CODE(p," orc_union64 _src1;\n"); + ORC_ASM_CODE(p," orc_union64 _src2;\n"); + ORC_ASM_CODE(p," _src1.i = ORC_DENORMAL_DOUBLE(%s);\n", src1); + ORC_ASM_CODE(p," _src2.i = ORC_DENORMAL_DOUBLE(%s);\n", src2); + ORC_ASM_CODE(p," if (ORC_ISNAN_DOUBLE(_src1.i)) %s = _src1.i;\n", dest); + ORC_ASM_CODE(p," else if (ORC_ISNAN_DOUBLE(_src2.i)) %s = _src2.i;\n", dest); + ORC_ASM_CODE(p," else %s = (_src1.f > _src2.f) ? _src1.i : _src2.i;\n", dest); + ORC_ASM_CODE(p," }\n"); +} + static OrcTarget c_target = { "c", FALSE, @@ -1136,7 +1314,15 @@ orc_c_init (void) orc_rule_register (rule_set, "splatw3q", c_rule_splatw3q, NULL); orc_rule_register (rule_set, "div255w", c_rule_div255w, NULL); orc_rule_register (rule_set, "divluw", c_rule_divluw, NULL); + orc_rule_register (rule_set, "convlf", c_rule_convlf, NULL); + orc_rule_register (rule_set, "convld", c_rule_convld, NULL); orc_rule_register (rule_set, "convfl", c_rule_convfl, NULL); orc_rule_register (rule_set, "convdl", c_rule_convdl, NULL); + orc_rule_register (rule_set, "convfd", c_rule_convfd, NULL); + orc_rule_register (rule_set, "convdf", c_rule_convdf, NULL); + orc_rule_register (rule_set, "minf", c_rule_minf, NULL); + orc_rule_register (rule_set, "maxf", c_rule_maxf, NULL); + orc_rule_register (rule_set, "mind", c_rule_mind, NULL); + orc_rule_register (rule_set, "maxd", c_rule_maxd, NULL); } -- 2.7.4