From 6867f973465329656dc333a307af6f42e46f7adc Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Fri, 14 Feb 2020 01:16:09 +0000 Subject: [PATCH 1/6] Fix bit operations failures on VS2019 32bit Working with Dirk Zimoch @dirk.zimoch, fixed various issues with bit operations on VS2019 32bit. These seem to relate to handling bit 31 of a 32 bit number. As EPICS << is an arithmetic bit shift, following Java we have added <<< and >>> operators for logical shifts Though it is on a different architecture, this looks like a similar issue to LP: #1838792 --- src/libCom/calc/calcPerform.c | 61 ++++++++++++++++++++----------- src/libCom/calc/postfix.c | 12 ++++-- src/libCom/calc/postfixPvt.h | 6 ++- src/libCom/test/epicsCalcTest.cpp | 37 +++++++++++++++++-- 4 files changed, 84 insertions(+), 32 deletions(-) diff --git a/src/libCom/calc/calcPerform.c b/src/libCom/calc/calcPerform.c index c0f4aebb8..1d675cffc 100644 --- a/src/libCom/calc/calcPerform.c +++ b/src/libCom/calc/calcPerform.c @@ -33,7 +33,7 @@ static int cond_search(const char **ppinst, int match); #endif /* Turn off global optimization for 64-bit MSVC builds */ -#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW) +#if 0 && defined(_WIN32) && defined(_M_X64) && !defined(_MINGW) # pragma optimize("g", off) #endif @@ -48,7 +48,6 @@ epicsShareFunc long double *ptop; /* stack pointer */ double top; /* value from top of stack */ epicsInt32 itop; /* integer from top of stack */ - epicsUInt32 utop; /* unsigned integer from top of stack */ int op; int nargs; @@ -287,30 +286,37 @@ epicsShareFunc long *ptop = ! *ptop; break; - /* For bitwise operations on values with bit 31 set, double values - * must first be cast to unsigned to correctly set that bit; the - * double value must be negative in that case. The result must be - * cast to a signed integer before converting to the double result. + /* Be VERY careful converting double to int in case bit 31 is set! + * Out-of-range errors give very different results on different sytems. + * Convert negative doubles to signed and positive doubles to unsigned + * first to avoid overflows if bit 32 is set. + * The result is always signed, values with bit 31 set are negative + * to avoid problems when writing the value to signed integer fields + * like longout.VAL or ao.RVAL. However unsigned fields may give + * problems on some architectures. (Fewer than giving problems with + * signed integer. Maybe the conversion functions should handle + * overflows better.) */ + #define d2i(x) ((x)<0?(epicsInt32)(x):(epicsInt32)(epicsUInt32)(x)) + #define d2ui(x) ((x)<0?(epicsUInt32)(epicsInt32)(x):(epicsUInt32)(x)) case BIT_OR: - utop = *ptop--; - *ptop = (epicsInt32) ((epicsUInt32) *ptop | utop); + top = *ptop--; + *ptop = (double)(d2i(*ptop) | d2i(top)); break; case BIT_AND: - utop = *ptop--; - *ptop = (epicsInt32) ((epicsUInt32) *ptop & utop); + top = *ptop--; + *ptop = (double)(d2i(*ptop) & d2i(top)); break; case BIT_EXCL_OR: - utop = *ptop--; - *ptop = (epicsInt32) ((epicsUInt32) *ptop ^ utop); + top = *ptop--; + *ptop = (double)(d2i(*ptop) ^ d2i(top)); break; case BIT_NOT: - utop = *ptop; - *ptop = (epicsInt32) ~utop; + *ptop = (double)~d2i(*ptop); break; /* The shift operators use signed integers, so a right-shift will @@ -318,14 +324,24 @@ epicsShareFunc long * double-casting through unsigned here is important, see above. */ - case RIGHT_SHIFT: - utop = *ptop--; - *ptop = ((epicsInt32) (epicsUInt32) *ptop) >> (utop & 31); + case RIGHT_SHIFT_ARITH: + top = *ptop--; + *ptop = (double)(d2i(*ptop) >> (d2i(top) & 31)); break; - case LEFT_SHIFT: - utop = *ptop--; - *ptop = ((epicsInt32) (epicsUInt32) *ptop) << (utop & 31); + case LEFT_SHIFT_ARITH: + top = *ptop--; + *ptop = (double)(d2i(*ptop) << (d2i(top) & 31)); + break; + + case RIGHT_SHIFT_LOGIC: + top = *ptop--; + *ptop = (double)(d2ui(*ptop) >> (d2ui(top) & 31u)); + break; + + case LEFT_SHIFT_LOGIC: + top = *ptop--; + *ptop = (double)(d2ui(*ptop) << (d2ui(top) & 31u)); break; case NOT_EQ: @@ -382,11 +398,12 @@ epicsShareFunc long *presult = *ptop; return 0; } -#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW) +#if 0 && defined(_WIN32) && defined(_M_X64) && !defined(_MINGW) # pragma optimize("", on) #endif - + + epicsShareFunc long calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores) { diff --git a/src/libCom/calc/postfix.c b/src/libCom/calc/postfix.c index 463ceea82..cf54eb8ec 100644 --- a/src/libCom/calc/postfix.c +++ b/src/libCom/calc/postfix.c @@ -148,13 +148,15 @@ static const ELEMENT operators[] = { {":=", 0, 0, -1, STORE_OPERATOR, STORE_A}, {";", 0, 0, 0, EXPR_TERMINATOR,NOT_GENERATED}, {"<", 3, 3, -1, BINARY_OPERATOR,LESS_THAN}, -{"<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT}, +{"<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT_ARITH}, +{"<<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT_LOGIC}, {"<=", 3, 3, -1, BINARY_OPERATOR,LESS_OR_EQ}, {"=", 3, 3, -1, BINARY_OPERATOR,EQUAL}, {"==", 3, 3, -1, BINARY_OPERATOR,EQUAL}, {">", 3, 3, -1, BINARY_OPERATOR,GR_THAN}, {">=", 3, 3, -1, BINARY_OPERATOR,GR_OR_EQ}, -{">>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT}, +{">>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT_ARITH}, +{">>>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT_LOGIC}, {"?", 0, 0, -1, CONDITIONAL, COND_IF}, {"AND", 2, 2, -1, BINARY_OPERATOR,BIT_AND}, {"OR", 1, 1, -1, BINARY_OPERATOR,BIT_OR}, @@ -579,8 +581,10 @@ epicsShareFunc void "BIT_AND", "BIT_EXCL_OR", "BIT_NOT", - "RIGHT_SHIFT", - "LEFT_SHIFT", + "RIGHT_SHIFT_ARITH", + "RIGHT_SHIFT_LOGIC", + "LEFT_SHIFT_ARITH", + "LEFT_SHIFT_LOGIC", /* Relationals */ "NOT_EQ", "LESS_THAN", diff --git a/src/libCom/calc/postfixPvt.h b/src/libCom/calc/postfixPvt.h index 53efb32e0..5b2ba0a7b 100644 --- a/src/libCom/calc/postfixPvt.h +++ b/src/libCom/calc/postfixPvt.h @@ -84,8 +84,10 @@ typedef enum { BIT_AND, BIT_EXCL_OR, BIT_NOT, - RIGHT_SHIFT, - LEFT_SHIFT, + RIGHT_SHIFT_ARITH, + RIGHT_SHIFT_LOGIC, + LEFT_SHIFT_ARITH, + LEFT_SHIFT_LOGIC, /* Relationals */ NOT_EQ, LESS_THAN, diff --git a/src/libCom/test/epicsCalcTest.cpp b/src/libCom/test/epicsCalcTest.cpp index 2492c95ba..a0131cd31 100644 --- a/src/libCom/test/epicsCalcTest.cpp +++ b/src/libCom/test/epicsCalcTest.cpp @@ -104,7 +104,7 @@ void testUInt32Calc(const char *expr, epicsUInt32 expected) { testDiag("calcPerform: error evaluating '%s'", expr); } - uresult = (epicsUInt32) result; + uresult = (result < 0.0 ? (epicsUInt32)(epicsInt32)result : (epicsUInt32)result); pass = (uresult == expected); if (!testOk(pass, "%s", expr)) { testDiag("Expected result is 0x%x (%u), actually got 0x%x (%u)", @@ -297,7 +297,7 @@ MAIN(epicsCalcTest) const double a=1.0, b=2.0, c=3.0, d=4.0, e=5.0, f=6.0, g=7.0, h=8.0, i=9.0, j=10.0, k=11.0, l=12.0; - testPlan(613); + testPlan(643); /* LITERAL_OPERAND elements */ testExpr(0); @@ -688,7 +688,9 @@ MAIN(epicsCalcTest) testExpr(NaN < NaN); testExpr(1 << 2); - testExpr(1 << 3 << 2) + testCalc("1 <<< 2", 1u << 2u); + testExpr(1 << 3 << 2); + testCalc("1 <<< 3 <<< 2", 1u << 3u << 2u); testExpr(0 <= 1); testExpr(0 <= 0); @@ -776,7 +778,9 @@ MAIN(epicsCalcTest) testExpr(NaN >= NaN); testExpr(8 >> 1); + testCalc("8 >>> 1", 8u >> 1u); testExpr(64 >> 2 >> 1); + testCalc("64 >>> 2 >>> 1", 64u >> 2u >> 1u); testExpr(7 AND 4); @@ -873,13 +877,19 @@ MAIN(epicsCalcTest) testExpr(2 | 4 / 2); // 1 5 testCalc("1 | 2 ** 3", 1 | (int) pow(2., 3.));// 1 6 testExpr(3 << 2 & 10); // 2 2 + testCalc("3 <<< 2 & 10", 3u << 2u & 10u); // 2 2 testCalc("18 & 6 << 2", (18 & 6) << 2); // 2 2 + testCalc("18 & 6 <<< 2", (18u & 6u) << 2u); // 2 2 testExpr(36 >> 2 & 10); // 2 2 + testCalc("36 >>> 2 & 10", 36u >> 2u & 10u); // 2 2 testCalc("18 & 20 >> 2", (18 & 20) >> 2); // 2 2 + testCalc("18 & 20 >>> 2", (18u & 20u) >> 2u); // 2 2 testExpr(3 & 4 == 4); // 2 3 testExpr(3 AND 4 == 4); // 2 3 testCalc("1 << 2 != 4", 1 << (2 != 4)); // 2 3 + testCalc("1 <<< 2 != 4", 1u << (2u != 4u)); // 2 3 testCalc("16 >> 2 != 4", 16 >> (2 != 4)); // 2 3 + testCalc("16 >>> 2 != 4", 16u >> (2u != 4u)); // 2 3 testExpr(3 AND -2); // 2 8 testExpr(0 < 1 ? 2 : 3); // 3 0 testExpr(1 <= 0 ? 2 : 3); // 3 0 @@ -951,7 +961,13 @@ MAIN(epicsCalcTest) testUInt32Calc("~0xaaaaaaaa", 0x55555555u); testUInt32Calc("~~0xaaaaaaaa", 0xaaaaaaaau); testUInt32Calc("0xaaaaaaaa >> 8", 0xffaaaaaau); + testUInt32Calc("0x55555555 >> 8", 0x00555555u); + testUInt32Calc("0xaaaaaaaa >>> 8", 0x00aaaaaau); + testUInt32Calc("0x55555555 >>> 8", 0x00555555u); testUInt32Calc("0xaaaaaaaa << 8", 0xaaaaaa00u); + testUInt32Calc("0x55555555 << 8", 0x55555500u); + testUInt32Calc("0xaaaaaaaa <<< 8", 0xaaaaaa00u); + testUInt32Calc("0x55555555 <<< 8", 0x55555500u); // using integer literals assigned to variables testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a AND b", 0xaaaa0000u); testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a OR b", 0xffffaaaau); @@ -959,7 +975,13 @@ MAIN(epicsCalcTest) testUInt32Calc("a:=0xaaaaaaaa; ~a", 0x55555555u); testUInt32Calc("a:=0xaaaaaaaa; ~~a", 0xaaaaaaaau); testUInt32Calc("a:=0xaaaaaaaa; a >> 8", 0xffaaaaaau); + testUInt32Calc("a:=0xaaaaaaaa; a >>> 8", 0x00aaaaaau); testUInt32Calc("a:=0xaaaaaaaa; a << 8", 0xaaaaaa00u); + testUInt32Calc("a:=0xaaaaaaaa; a <<< 8", 0xaaaaaa00u); + testUInt32Calc("a:=0x55555555; a >> 8", 0x00555555u); + testUInt32Calc("a:=0x55555555; a >>> 8", 0x00555555u); + testUInt32Calc("a:=0x55555555; a << 8", 0x55555500u); + testUInt32Calc("a:=0x55555555; a <<< 8", 0x55555500u); // Test proper conversion of double values (+ 0.1 enforces double literal) // when used as inputs to the bitwise operations. @@ -979,14 +1001,21 @@ MAIN(epicsCalcTest) testUInt32Calc("~ -1431655766.1", 0x55555555u); testUInt32Calc("~ 2863311530.1", 0x55555555u); testUInt32Calc("-1431655766.1 >> 0", 0xaaaaaaaau); + testUInt32Calc("-1431655766.1 >>> 0", 0xaaaaaaaau); testUInt32Calc("2863311530.1 >> 0", 0xaaaaaaaau); + testUInt32Calc("2863311530.1 >>> 0", 0xaaaaaaaau); testUInt32Calc("-1431655766.1 >> 0.1", 0xaaaaaaaau); + testUInt32Calc("-1431655766.1 >>> 0.1", 0xaaaaaaaau); testUInt32Calc("2863311530.1 >> 0.1", 0xaaaaaaaau); + testUInt32Calc("2863311530.1 >>> 0.1", 0xaaaaaaaau); testUInt32Calc("-1431655766.1 << 0", 0xaaaaaaaau); + testUInt32Calc("-1431655766.1 <<< 0", 0xaaaaaaaau); testUInt32Calc("2863311530.1 << 0", 0xaaaaaaaau); + testUInt32Calc("2863311530.1 <<< 0", 0xaaaaaaaau); testUInt32Calc("-1431655766.1 << 0.1", 0xaaaaaaaau); + testUInt32Calc("-1431655766.1 <<< 0.1", 0xaaaaaaaau); testUInt32Calc("2863311530.1 << 0.1", 0xaaaaaaaau); + testUInt32Calc("2863311530.1 <<< 0.1", 0xaaaaaaaau); return testDone(); } - From 803593560dc160ef5c971ef04908574e6dc88c37 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Mon, 17 Feb 2020 12:22:20 +0000 Subject: [PATCH 2/6] Remove redundant left logical shift --- src/libCom/calc/calcPerform.c | 24 ++++++------------------ src/libCom/calc/postfix.c | 4 +--- src/libCom/calc/postfixPvt.h | 3 +-- src/libCom/test/epicsCalcTest.cpp | 15 +-------------- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/src/libCom/calc/calcPerform.c b/src/libCom/calc/calcPerform.c index 1d675cffc..4a073c774 100644 --- a/src/libCom/calc/calcPerform.c +++ b/src/libCom/calc/calcPerform.c @@ -32,11 +32,6 @@ static int cond_search(const char **ppinst, int match); #define PI 3.14159265358979323 #endif -/* Turn off global optimization for 64-bit MSVC builds */ -#if 0 && defined(_WIN32) && defined(_M_X64) && !defined(_MINGW) -# pragma optimize("g", off) -#endif - /* calcPerform * * Evalutate the postfix expression @@ -319,9 +314,12 @@ epicsShareFunc long *ptop = (double)~d2i(*ptop); break; - /* The shift operators use signed integers, so a right-shift will - * extend the sign bit into the left-hand end of the value. The - * double-casting through unsigned here is important, see above. + /* In C the shift operators decide on an arithmetic or logical shift + * based on whether the integer is signed or unsigned. + * With signed integers, a right-shift is arithmetic and will + * extend the sign bit into the left-hand end of the value. When used + * with unsigned values a logical shift is performed. The + * double-casting through signed/unsigned here is important, see above. */ case RIGHT_SHIFT_ARITH: @@ -339,11 +337,6 @@ epicsShareFunc long *ptop = (double)(d2ui(*ptop) >> (d2ui(top) & 31u)); break; - case LEFT_SHIFT_LOGIC: - top = *ptop--; - *ptop = (double)(d2ui(*ptop) << (d2ui(top) & 31u)); - break; - case NOT_EQ: top = *ptop--; *ptop = *ptop != top; @@ -398,11 +391,6 @@ epicsShareFunc long *presult = *ptop; return 0; } -#if 0 && defined(_WIN32) && defined(_M_X64) && !defined(_MINGW) -# pragma optimize("", on) -#endif - - epicsShareFunc long calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores) diff --git a/src/libCom/calc/postfix.c b/src/libCom/calc/postfix.c index cf54eb8ec..54d629b40 100644 --- a/src/libCom/calc/postfix.c +++ b/src/libCom/calc/postfix.c @@ -149,7 +149,6 @@ static const ELEMENT operators[] = { {";", 0, 0, 0, EXPR_TERMINATOR,NOT_GENERATED}, {"<", 3, 3, -1, BINARY_OPERATOR,LESS_THAN}, {"<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT_ARITH}, -{"<<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT_LOGIC}, {"<=", 3, 3, -1, BINARY_OPERATOR,LESS_OR_EQ}, {"=", 3, 3, -1, BINARY_OPERATOR,EQUAL}, {"==", 3, 3, -1, BINARY_OPERATOR,EQUAL}, @@ -582,9 +581,8 @@ epicsShareFunc void "BIT_EXCL_OR", "BIT_NOT", "RIGHT_SHIFT_ARITH", - "RIGHT_SHIFT_LOGIC", "LEFT_SHIFT_ARITH", - "LEFT_SHIFT_LOGIC", + "RIGHT_SHIFT_LOGIC", /* Relationals */ "NOT_EQ", "LESS_THAN", diff --git a/src/libCom/calc/postfixPvt.h b/src/libCom/calc/postfixPvt.h index 5b2ba0a7b..739cdbb78 100644 --- a/src/libCom/calc/postfixPvt.h +++ b/src/libCom/calc/postfixPvt.h @@ -85,9 +85,8 @@ typedef enum { BIT_EXCL_OR, BIT_NOT, RIGHT_SHIFT_ARITH, - RIGHT_SHIFT_LOGIC, LEFT_SHIFT_ARITH, - LEFT_SHIFT_LOGIC, + RIGHT_SHIFT_LOGIC, /* Relationals */ NOT_EQ, LESS_THAN, diff --git a/src/libCom/test/epicsCalcTest.cpp b/src/libCom/test/epicsCalcTest.cpp index a0131cd31..5f7d68826 100644 --- a/src/libCom/test/epicsCalcTest.cpp +++ b/src/libCom/test/epicsCalcTest.cpp @@ -297,7 +297,7 @@ MAIN(epicsCalcTest) const double a=1.0, b=2.0, c=3.0, d=4.0, e=5.0, f=6.0, g=7.0, h=8.0, i=9.0, j=10.0, k=11.0, l=12.0; - testPlan(643); + testPlan(630); /* LITERAL_OPERAND elements */ testExpr(0); @@ -688,9 +688,7 @@ MAIN(epicsCalcTest) testExpr(NaN < NaN); testExpr(1 << 2); - testCalc("1 <<< 2", 1u << 2u); testExpr(1 << 3 << 2); - testCalc("1 <<< 3 <<< 2", 1u << 3u << 2u); testExpr(0 <= 1); testExpr(0 <= 0); @@ -877,9 +875,7 @@ MAIN(epicsCalcTest) testExpr(2 | 4 / 2); // 1 5 testCalc("1 | 2 ** 3", 1 | (int) pow(2., 3.));// 1 6 testExpr(3 << 2 & 10); // 2 2 - testCalc("3 <<< 2 & 10", 3u << 2u & 10u); // 2 2 testCalc("18 & 6 << 2", (18 & 6) << 2); // 2 2 - testCalc("18 & 6 <<< 2", (18u & 6u) << 2u); // 2 2 testExpr(36 >> 2 & 10); // 2 2 testCalc("36 >>> 2 & 10", 36u >> 2u & 10u); // 2 2 testCalc("18 & 20 >> 2", (18 & 20) >> 2); // 2 2 @@ -887,7 +883,6 @@ MAIN(epicsCalcTest) testExpr(3 & 4 == 4); // 2 3 testExpr(3 AND 4 == 4); // 2 3 testCalc("1 << 2 != 4", 1 << (2 != 4)); // 2 3 - testCalc("1 <<< 2 != 4", 1u << (2u != 4u)); // 2 3 testCalc("16 >> 2 != 4", 16 >> (2 != 4)); // 2 3 testCalc("16 >>> 2 != 4", 16u >> (2u != 4u)); // 2 3 testExpr(3 AND -2); // 2 8 @@ -966,8 +961,6 @@ MAIN(epicsCalcTest) testUInt32Calc("0x55555555 >>> 8", 0x00555555u); testUInt32Calc("0xaaaaaaaa << 8", 0xaaaaaa00u); testUInt32Calc("0x55555555 << 8", 0x55555500u); - testUInt32Calc("0xaaaaaaaa <<< 8", 0xaaaaaa00u); - testUInt32Calc("0x55555555 <<< 8", 0x55555500u); // using integer literals assigned to variables testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a AND b", 0xaaaa0000u); testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a OR b", 0xffffaaaau); @@ -977,11 +970,9 @@ MAIN(epicsCalcTest) testUInt32Calc("a:=0xaaaaaaaa; a >> 8", 0xffaaaaaau); testUInt32Calc("a:=0xaaaaaaaa; a >>> 8", 0x00aaaaaau); testUInt32Calc("a:=0xaaaaaaaa; a << 8", 0xaaaaaa00u); - testUInt32Calc("a:=0xaaaaaaaa; a <<< 8", 0xaaaaaa00u); testUInt32Calc("a:=0x55555555; a >> 8", 0x00555555u); testUInt32Calc("a:=0x55555555; a >>> 8", 0x00555555u); testUInt32Calc("a:=0x55555555; a << 8", 0x55555500u); - testUInt32Calc("a:=0x55555555; a <<< 8", 0x55555500u); // Test proper conversion of double values (+ 0.1 enforces double literal) // when used as inputs to the bitwise operations. @@ -1009,13 +1000,9 @@ MAIN(epicsCalcTest) testUInt32Calc("2863311530.1 >> 0.1", 0xaaaaaaaau); testUInt32Calc("2863311530.1 >>> 0.1", 0xaaaaaaaau); testUInt32Calc("-1431655766.1 << 0", 0xaaaaaaaau); - testUInt32Calc("-1431655766.1 <<< 0", 0xaaaaaaaau); testUInt32Calc("2863311530.1 << 0", 0xaaaaaaaau); - testUInt32Calc("2863311530.1 <<< 0", 0xaaaaaaaau); testUInt32Calc("-1431655766.1 << 0.1", 0xaaaaaaaau); - testUInt32Calc("-1431655766.1 <<< 0.1", 0xaaaaaaaau); testUInt32Calc("2863311530.1 << 0.1", 0xaaaaaaaau); - testUInt32Calc("2863311530.1 <<< 0.1", 0xaaaaaaaau); return testDone(); } From 8250339e0df18d7922dce4eb70ee44ed7a6d2bd7 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Mon, 17 Feb 2020 12:46:11 +0000 Subject: [PATCH 3/6] Update record pod documentation --- src/std/rec/calcRecord.dbd.pod | 7 +++++-- src/std/rec/calcoutRecord.dbd.pod | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/std/rec/calcRecord.dbd.pod b/src/std/rec/calcRecord.dbd.pod index 243c81eee..83b8edd76 100644 --- a/src/std/rec/calcRecord.dbd.pod +++ b/src/std/rec/calcRecord.dbd.pod @@ -318,10 +318,13 @@ XOR : Bitwise Exclusive Or C<~> : One's Complement =item * -C<<< << >>> : Left shift +C<<< << >>> : Arithmetic Left Shift =item * -C<<< >> >>> : Right shift +C<<< >> >>> : Arithmetic Right Shift + +=item * +C<<<< >>> >>>> : Logical Right Shift =back diff --git a/src/std/rec/calcoutRecord.dbd.pod b/src/std/rec/calcoutRecord.dbd.pod index a59eaa348..9a1393d73 100644 --- a/src/std/rec/calcoutRecord.dbd.pod +++ b/src/std/rec/calcoutRecord.dbd.pod @@ -350,11 +350,13 @@ XOR : Bitwise Exclusive Or C<~> : One's Complement =item * -C<<< << >>> : Left shift +C<<< << >>> : Arithmetic Left Shift =item * -C<<< >> >>> : Right shift +C<<< >> >>> : Arithmetic Right Shift +=item * +C<<<< >>> >>>> : Logical Right Shift =back =head3 Assignment Operator From f2b4c412d3aa14bdf4c86fc3cd61d9cf482b4a99 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Mon, 17 Feb 2020 12:49:45 +0000 Subject: [PATCH 4/6] Fix doc typo --- src/std/rec/calcoutRecord.dbd.pod | 1 + 1 file changed, 1 insertion(+) diff --git a/src/std/rec/calcoutRecord.dbd.pod b/src/std/rec/calcoutRecord.dbd.pod index 9a1393d73..a9b2a4e59 100644 --- a/src/std/rec/calcoutRecord.dbd.pod +++ b/src/std/rec/calcoutRecord.dbd.pod @@ -357,6 +357,7 @@ C<<< >> >>> : Arithmetic Right Shift =item * C<<<< >>> >>>> : Logical Right Shift + =back =head3 Assignment Operator From a0667a122bd2e4ac9fd01f3c554a43b040e8d9e0 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Mon, 17 Feb 2020 13:29:38 +0000 Subject: [PATCH 5/6] Excluded x64 tests now need to be excluded on x86 too --- src/libCom/test/epicsCalcTest.cpp | 4 ++-- src/libCom/test/epicsMathTest.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libCom/test/epicsCalcTest.cpp b/src/libCom/test/epicsCalcTest.cpp index 5f7d68826..ee2108ffb 100644 --- a/src/libCom/test/epicsCalcTest.cpp +++ b/src/libCom/test/epicsCalcTest.cpp @@ -612,14 +612,14 @@ MAIN(epicsCalcTest) testExpr(0.0 + NaN); testExpr(Inf + 0.0); testExpr(Inf + Inf); -#if defined(_WIN64) && defined(_MSC_VER) +#if defined(_WIN32) && defined(_MSC_VER) testCalc("Inf + -Inf", NaN); #else testExpr(Inf + -Inf); #endif testExpr(Inf + NaN); testExpr(-Inf + 0.0); -#if defined(_WIN64) && defined(_MSC_VER) +#if defined(_WIN32) && defined(_MSC_VER) testCalc("-Inf + Inf", NaN); #else testExpr(-Inf + Inf); diff --git a/src/libCom/test/epicsMathTest.c b/src/libCom/test/epicsMathTest.c index 8ea763cf0..ffb2426fd 100644 --- a/src/libCom/test/epicsMathTest.c +++ b/src/libCom/test/epicsMathTest.c @@ -32,23 +32,23 @@ MAIN(epicsMathTest) testOk1(epicsINF > 0.0); testOk1(epicsINF - epicsINF != 0.0); -#if defined(_WIN64) && defined(_MSC_VER) - testTodoBegin("Known failure on windows-x64"); +#if defined(_WIN32) && defined(_MSC_VER) + testTodoBegin("Known failure on windows-x64 and win32-x86"); #endif testOk1(epicsINF + -epicsINF != 0.0); testOk1(-epicsINF + epicsINF != 0.0); -#if defined(_WIN64) && defined(_MSC_VER) +#if defined(_WIN32) && defined(_MSC_VER) testTodoEnd(); #endif testOk1(isnan(epicsINF - epicsINF)); -#if defined(_WIN64) && defined(_MSC_VER) - testTodoBegin("Known failure on windows-x64"); +#if defined(_WIN32) && defined(_MSC_VER) + testTodoBegin("Known failure on windows-x64 and win32-x86"); #endif testOk1(isnan(epicsINF + -epicsINF)); testOk1(isnan(-epicsINF + epicsINF)); -#if defined(_WIN64) && defined(_MSC_VER) +#if defined(_WIN32) && defined(_MSC_VER) testTodoEnd(); #endif @@ -62,12 +62,12 @@ MAIN(epicsMathTest) testOk1(!(epicsNAN > epicsNAN)); testOk1(isnan(epicsNAN - epicsNAN)); -#if defined(_WIN64) && defined(_MSC_VER) - testTodoBegin("Known failure on windows-x64"); +#if defined(_WIN32) && defined(_MSC_VER) + testTodoBegin("Known failure on windows-x64 and win32-x86"); #endif testOk1(isnan(epicsNAN + -epicsNAN)); testOk1(isnan(-epicsNAN + epicsNAN)); -#if defined(_WIN64) && defined(_MSC_VER) +#if defined(_WIN32) && defined(_MSC_VER) testTodoEnd(); #endif From 3944b32e048b4362808ffa847cd2feb7d3525e06 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Mon, 17 Feb 2020 13:30:15 +0000 Subject: [PATCH 6/6] Add back in optimisation disable --- src/libCom/calc/calcPerform.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libCom/calc/calcPerform.c b/src/libCom/calc/calcPerform.c index 4a073c774..40e173b61 100644 --- a/src/libCom/calc/calcPerform.c +++ b/src/libCom/calc/calcPerform.c @@ -25,6 +25,7 @@ #include "postfix.h" #include "postfixPvt.h" + static double calcRandom(void); static int cond_search(const char **ppinst, int match); @@ -32,6 +33,11 @@ static int cond_search(const char **ppinst, int match); #define PI 3.14159265358979323 #endif +/* Turn off global optimization for 64-bit MSVC builds */ +#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW) +# pragma optimize("g", off) +#endif + /* calcPerform * * Evalutate the postfix expression @@ -392,6 +398,10 @@ epicsShareFunc long return 0; } +#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW) +# pragma optimize("", on) +#endif + epicsShareFunc long calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores) {