History

Implement proper floating point negation

Using "-0.0 - x" still isn't enough if x is a NaN, so bite the bullet and implement sign-bit flipping via memory. (It's usually not too bad, the -0.0-x method also uses memory for the floating point constant). This way is at least shorter than implementing a new top-level operation for all backends (a negate) that would be unary.

Michael Matz committed 5 years ago

Commit 29d88711 parent 4c951692 files · +48 −13Browse files

Unified · Split

2 files
  1. tccgen.c +41 −13
  2. tests/tcctest.c +7 −0
tccgen.c+41−13
@@ -5880,19 +5880,47 @@ ST_FUNC void unary(void) · 5879 unmodified lines
5880 unary();5880 unary();
5881 t = vtop->type.t & VT_BTYPE;5881 t = vtop->type.t & VT_BTYPE;
5882 if (is_float(t)) {5882 if (is_float(t)) {
5883 /* In IEEE negate(x) isn't subtract(0,x), but rather5883 if ((vtop->r & VT_VALMASK) == VT_CONST) {
5884 subtract(-0, x). */5884 /* This is what gen_opif would do if we had a NEG operation. */
5885 vpush(&vtop->type);5885 if (t == VT_FLOAT)
5886 if (t == VT_FLOAT)5886 vtop->c.f = -vtop->c.f;
5887 vtop->c.f = -1.0 * 0.0;5887 else if (t == VT_DOUBLE)
5888 else if (t == VT_DOUBLE)5888 vtop->c.d = -vtop->c.d;
5889 vtop->c.d = -1.0 * 0.0;5889 else
5890 else5890 vtop->c.ld = -vtop->c.ld;
5891 vtop->c.ld = -1.0 * 0.0;5891 } else {
5892 } else5892 /* In IEEE negate(x) isn't subtract(0,x). Without NaNs it's
5893 vpushi(0);5893 subtract(-0, x), but with them it's really a sign flip
5894 vswap();5894 operation. We implement this with bit manipulation and have
5895 gen_op('-');5895 to do some type reinterpretation for this, which TCC can do
5896 only via memory. */
5897 int align, size = type_size(&vtop->type, &align);
5898 save_reg(gv(RC_TYPE(t)));
5899 vdup();
5900 gaddrof();
5901 vtop->type = char_pointer_type;
5902 /* Byte of sign bit. For big endian, this would have to
5903 add zero always. */
5904#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_I386)
5905 /* sizeof long double is 12 or 16 here, but it's
5906 really the 80bit extended float format. */
5907 if (t == VT_LDOUBLE)
5908 size = 10;
5909#endif
5910 vpushi(size - 1);
5911 gen_op('+');
5912 indir();
5913 vdup();
5914 vpushi(0x80); /* flip sign */
5915 gen_op('^');
5916 vstore();
5917 vpop();
5918 }
5919 } else {
5920 vpushi(0);
5921 vswap();
5922 gen_op('-');
5923 }
5896 break;5924 break;
5897 case TOK_LAND:5925 case TOK_LAND:
5898 if (!gnu_ext)5926 if (!gnu_ext)
tests/tcctest.c+7−0
@@ -2227,6 +2227,12 @@ void prefix ## signed_zeros(void) \ · 2226 unmodified lines
2227 else\2227 else\
2228 printf ("x != -y; this is wrong!\n");\2228 printf ("x != -y; this is wrong!\n");\
2229}\2229}\
2230void prefix ## nan(void)\
2231{\
2232 type nan = 0.0/0.0;\
2233 type nnan = -nan; \
2234 printf("nantest: " fmt " " fmt "\n", nan, nnan);\
2235}\
2230void prefix ## test(void)\2236void prefix ## test(void)\
2231{\2237{\
2232 printf("testing '%s'\n", #typename);\2238 printf("testing '%s'\n", #typename);\
@@ -2237,6 +2243,7 @@ void prefix ## test(void)\ · 4 unmodified lines
2237 prefix ## fcast(-2334.6);\2243 prefix ## fcast(-2334.6);\
2238 prefix ## call();\2244 prefix ## call();\
2239 prefix ## signed_zeros();\2245 prefix ## signed_zeros();\
2246 prefix ## nan();\
2240}2247}
2241 2248
2242FTEST(f, float, float, "%f")2249FTEST(f, float, float, "%f")

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t