+ if (attr == (FLOAT | (FLOAT >> 1)))
+ {
+ // Float > Float
+ double * dst = (double *)sval;
+ double * src = (double *)(sval + 1);
+ *sval = *dst > *src;
+ }
+ else if (attr == FLOAT)
+ {
+ // Float > Int
+ double * dst = (double *)sval;
+ uint64_t * src = (uint64_t *)(sval + 1);
+ *sval = *dst > *src;
+ }
+ else if (attr == FLOAT >> 1)
+ {
+ // Int > Float
+ uint64_t * dst = (uint64_t *)sval;
+ double * src = (double *)(sval + 1);
+ *sval = *dst > *src;
+ }
+ else
+= {
+ *sval = *sval > sval[1];
+ }
+
+ *sattr = ABS | DEFINED;
+
+ break;
+ case '<':
+//printf("evexpr(): <\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ return error(seg_error);
+
+ // Extract float attributes from both terms and pack them
+ // into a single value
+ attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) > >1);
+
+ if (attr == (FLOAT | (FLOAT >> 1)))
+ {
+ // Float < Float
+ double * dst = (double *)sval;
+ double * src = (double *)(sval + 1);
+ *sval = *dst < *src;
+ }
+ else if (attr == FLOAT)
+ {
+ // Float < Int
+ double * dst = (double *)sval;
+ uint64_t * src = (uint64_t *)(sval + 1);
+ *sval = *dst < *src;
+ }
+ else if (attr == FLOAT >> 1)
+ {
+ // Int < Float
+ uint64_t * dst = (uint64_t *)sval;
+ double * src = (double *)(sval + 1);
+ *sval = *dst < *src;
+ }
+ else
+ {
+ *sval = *sval < sval[1];
+ }
+
+ *sattr = ABS | DEFINED;
+
+ break;
+ case NE:
+//printf("evexpr(): NE\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ return error(seg_error);
+
+ // Extract float attributes from both terms and pack them
+ // into a single value
+ attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+
+ if (attr == (FLOAT | (FLOAT >> 1)))
+ {
+ // Float <> Float
+ return error("comparison for equality with float types not allowed.");
+ }
+ else if (attr == FLOAT)
+ {
+ // Float <> Int
+ return error("comparison for equality with float types not allowed.");
+ }
+ else if (attr == FLOAT >> 1)
+ {
+ // Int != Float
+ return error("comparison for equality with float types not allowed.");
+ }
+ else
+ {
+ *sval = *sval != sval[1];
+ }
+
+ *sattr = ABS | DEFINED;
+
+ break;
+ case '=':
+//printf("evexpr(): =\n");
+ sattr--;
+ sval--;
+
+ if ((*sattr & TDB) != (sattr[1] & TDB))
+ return error(seg_error);
+
+ // Extract float attributes from both terms and pack them
+ // into a single value
+ attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+
+ if (attr == (FLOAT | (FLOAT >> 1)))
+ {
+ // Float = Float
+ double * dst = (double *)sval;
+ double * src = (double *)(sval + 1);
+ *sval = *src == *dst;
+ }
+ else if (attr == FLOAT)
+ {
+ // Float = Int
+ return error("equality with float ");
+ }
+ else if (attr == FLOAT >> 1)
+ {
+ // Int == Float
+ uint64_t * dst = (uint64_t *)sval;
+ double * src = (double *)(sval + 1);
+ *sval = *src == *dst;
+ }
+ else
+ {
+ *sval = *sval == sval[1];
+ }
+
+ *sattr = ABS | DEFINED;
+
+ break;
+ // All other binary operators must have two ABS items
+ // to work with. They all produce an ABS value.
+ default:
+//printf("evexpr(): default\n");
+ // GH - Removed for v1.0.15 as part of the fix for indexed loads.
+ //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
+ //error(seg_error);
+
+ switch ((int)tk[-1])
+ {
+ case '*':
+ sval--;
+ sattr--; // Pop attrib
+//printf("--> NxN: %i x %i = ", *sval, sval[1]);
+ // Extract float attributes from both terms and pack them
+ // into a single value
+ attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+ attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
+
+ if (attr == (FLOAT | (FLOAT >> 1)))
+ {
+ // Float * Float
+ double * dst = (double *)sval;
+ double * src = (double *)(sval + 1);
+ *dst *= *src;
+ }
+ else if (attr == FLOAT)
+ {
+ // Float * Int
+ double * dst = (double *)sval;
+ uint64_t * src = (uint64_t *)(sval + 1);
+ *dst *= *src;
+ }
+ else if (attr == FLOAT >> 1)
+ {
+ // Int * Float
+ uint64_t * dst = (uint64_t *)sval;
+ double * src = (double *)(sval + 1);
+ *(double *)dst = *src * *dst;
+ }
+ else
+ {
+ *sval *= sval[1];
+ }
+//printf("%i\n", *sval);
+
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sattr |= attr2;
+
+ break;
+ case '/':
+ sval--;
+ sattr--; // Pop attrib
+
+
+//printf("--> N/N: %i / %i = ", sval[0], sval[1]);
+ // Extract float attributes from both terms and pack them
+ // into a single value
+ attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+ attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
+
+ if (attr == (FLOAT | (FLOAT >> 1)))
+ {
+ // Float / Float
+ double * dst = (double *)sval;
+ double * src = (double *)(sval + 1);
+ if (*src == 0)
+ return error("divide by zero");
+ *dst = *dst / *src;
+ }
+ else if (attr == FLOAT)
+ {
+ // Float / Int
+ double * dst = (double *)sval;
+ uint64_t * src = (uint64_t *)(sval + 1);
+ if (*src == 0)
+ return error("divide by zero");
+ *dst = *dst / *src;
+ }
+ else if (attr == FLOAT >> 1)
+ {
+ // Int / Float
+ uint64_t * dst=(uint64_t *)sval;
+ double * src=(double *)(sval + 1);
+ if (*src == 0)
+ return error("divide by zero");
+ *(double *)dst = *dst / *src;
+ }
+ else
+ {
+ if (sval[1] == 0)
+ return error("divide by zero");
+//printf("--> N/N: %i / %i = ", sval[0], sval[1]);
+ // Compiler is picky here: Without casting these, it discards
+ // the sign if dividing a negative # by a positive one,
+ // creating a bad result. :-/
+ // Definitely a side effect of using uint32_ts intead of ints.
+ *sval = (int32_t)sval[0] / (int32_t)sval[1];
+ }
+
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sattr |= attr2;
+
+//printf("%i\n", *sval);
+ break;
+ case '%':
+ sval--;
+ sattr--; // Pop attrib
+ if ((*sattr | sattr[1]) & FLOAT)
+ return error("floating point numbers not allowed with operator '%'.");
+
+ if (sval[1] == 0)
+ return error("mod (%) by zero");
+
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sval %= sval[1];
+ break;
+ case SHL:
+ sval--;
+ sattr--; // Pop attrib
+ if ((*sattr | sattr[1]) & FLOAT)
+ return error("floating point numbers not allowed with operator '<<'.");
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sval <<= sval[1];
+ break;
+ case SHR:
+ sval--;
+ sattr--; // Pop attrib
+ if ((*sattr | sattr[1]) & FLOAT)
+ return error("floating point numbers not allowed with operator '>>'.");
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sval >>= sval[1];
+ break;
+ case '&':
+ sval--;
+ sattr--; // Pop attrib
+ if ((*sattr | sattr[1]) & FLOAT)
+ return error("floating point numbers not allowed with operator '&'.");
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sval &= sval[1];
+ break;
+ case '^':
+ sval--;
+ sattr--; // Pop attrib
+ if ((*sattr | sattr[1]) & FLOAT)
+ return error("floating point numbers not allowed with operator '^'.");
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sval ^= sval[1];
+ break;
+ case '|':
+ sval--;
+ sattr--; // Pop attrib
+ if ((*sattr | sattr[1]) & FLOAT)
+ return error("floating point numbers not allowed with operator '|'.");
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sval |= sval[1];
+ break;
+ default:
+ interror(5); // Bad operator in expression stream
+ }
+ }
+ }
+
+ if (esym != NULL)
+ *sattr &= ~DEFINED;
+
+ if (a_esym != NULL)
+ *a_esym = esym;
+
+ // sym_seg added in 1.0.16 to solve a problem with forward symbols in
+ // expressions where absolute values also existed. The absolutes were
+ // overiding the symbol segments and not being included :(
+ //*a_attr = *sattr | sym_seg; // Copy value + attrib
+
+ *a_attr = *sattr; // Copy value + attrib
+ *a_value = *sval;
+
+ return OK;
+}