]> Shamusworld >> Repos - rmac/blob - expr.c
Added floating point support to expression evaluator, introduced FLOAT token, fixup...
[rmac] / expr.c
1 //
2 // RMAC - Reboot's Macro Assembler for all Atari computers
3 // EXPR.C - Expression Analyzer
4 // Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
7 //
8
9 #include "expr.h"
10 #include "direct.h"
11 #include "error.h"
12 #include "listing.h"
13 #include "mach.h"
14 #include "procln.h"
15 #include "riscasm.h"
16 #include "sect.h"
17 #include "symbol.h"
18 #include "token.h"
19
20 #define DEF_KW                                          // Declare keyword values
21 #include "kwtab.h"                                      // Incl generated keyword tables & defs
22
23 // N.B.: The size of tokenClass should be identical to the largest value of
24 //       a token; we're assuming 256 but not 100% sure!
25 static char tokenClass[256];            // Generated table of token classes
26 static uint64_t evstk[EVSTACKSIZE];     // Evaluator value stack
27 static WORD evattr[EVSTACKSIZE];        // Evaluator attribute stack
28
29 // Token-class initialization list
30 char itokcl[] = {
31         0,                                                              // END
32         CONST, FCONST, SYMBOL, 0,               // ID
33         '(', '[', '{', 0,                               // OPAR
34         ')', ']', '}', 0,                               // CPAR
35         CR_DEFINED, CR_REFERENCED,              // SUNARY (special unary)
36         CR_STREQ, CR_MACDEF,
37         CR_DATE, CR_TIME,
38         CR_ABSCOUNT, 0,
39         '!', '~', UNMINUS, 0,                   // UNARY
40         '*', '/', '%', 0,                               // MULT
41         '+', '-', 0,                                    // ADD
42         SHL, SHR, 0,                                    // SHIFT
43         LE, GE, '<', '>', NE, '=', 0,   // REL
44         '&', 0,                                                 // AND
45         '^', 0,                                                 // XOR
46         '|', 0,                                                 // OR
47         1                                                               // (the end)
48 };
49
50 const char missym_error[] = "missing symbol";
51 const char str_error[] = "missing symbol or string";
52
53 // Convert expression to postfix
54 static TOKEN * evalTokenBuffer;         // Deposit tokens here (this is really a
55                                                                         // pointer to exprbuf from direct.c)
56                                                                         // (Can also be from others, like
57                                                                         // riscasm.c)
58 static int symbolNum;                           // Pointer to the entry in symbolPtr[]
59
60
61 //
62 // Obtain a string value
63 //
64 static uint32_t str_value(char * p)
65 {
66         uint32_t v;
67
68         for(v=0; *p; p++)
69                 v = (v << 8) | (*p & 0xFF);
70
71         return v;
72 }
73
74
75 //
76 // Initialize expression analyzer
77 //
78 void InitExpression(void)
79 {
80         // Initialize token-class table (all set to END)
81         for(int i=0; i<256; i++)
82                 tokenClass[i] = END;
83
84         int i = 0;
85
86         for(char * p=itokcl; *p!=1; p++)
87         {
88                 if (*p == 0)
89                         i++;
90                 else
91                         tokenClass[(int)(*p)] = (char)i;
92         }
93
94         symbolNum = 0;
95 }
96
97
98 //
99 // Binary operators (all the same precedence)
100 //
101 int expr0(void)
102 {
103         TOKEN t;
104
105         if (expr1() != OK)
106                 return ERROR;
107
108         while (tokenClass[*tok] >= MULT)
109         {
110                 t = *tok++;
111
112                 if (expr1() != OK)
113                         return ERROR;
114
115                 *evalTokenBuffer++ = t;
116         }
117
118         return OK;
119 }
120
121
122 //
123 // Unary operators (detect unary '-')
124 // ggn: If expression starts with a plus then also eat it up.
125 //      For some reason the parser gets confused when this happens and
126 //      emits a "bad expression".
127 //
128 int expr1(void)
129 {
130         int class;
131         TOKEN t;
132         SYM * sy;
133         char * p, * p2;
134         WORD w;
135         int j;
136         uint64_t * evalTokenBuffer64;
137
138         class = tokenClass[*tok];
139
140         if (*tok == '-' || *tok == '+' || class == UNARY)
141         {
142                 t = *tok++;
143
144                 if (expr2() != OK)
145                         return ERROR;
146
147                 if (t == '-')
148                         t = UNMINUS;
149
150                 // With leading + we don't have to deposit
151                 // anything to the buffer because there's
152                 // no unary '+' nor we have to do anything about it
153                 if (t != '+')
154                 *evalTokenBuffer++ = t;
155         }
156         else if (class == SUNARY)
157         {
158                 switch ((int)*tok++)
159                 {
160                 case CR_ABSCOUNT:
161                         *evalTokenBuffer++ = CONST;
162                         evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
163                         *evalTokenBuffer64++ = (LONG)sect[ABS].sloc;
164                         evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
165                         break;
166                 case CR_TIME:
167                         *evalTokenBuffer++ = CONST;
168                         evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
169                         *evalTokenBuffer64++ = dos_time();
170                         evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
171                         break;
172                 case CR_DATE:
173                         *evalTokenBuffer++ = CONST;
174                         evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
175                         *evalTokenBuffer64++ = dos_date();
176                         evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
177                         break;
178                 case CR_MACDEF:                                    // ^^macdef <macro-name>
179                         if (*tok++ != SYMBOL)
180                                 return error(missym_error);
181
182                         p = string[*tok++];
183                         w = (lookup(p, MACRO, 0) == NULL ? 0 : 1);
184                         evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
185                         *evalTokenBuffer64++ = (TOKEN)w;
186                         evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
187                         *evalTokenBuffer++ = (TOKEN)w;
188                         break;
189                 case CR_DEFINED:
190                         w = DEFINED;
191                         goto getsym;
192                 case CR_REFERENCED:
193                         w = REFERENCED;
194 getsym:
195                         if (*tok++ != SYMBOL)
196                                 return error(missym_error);
197
198                         p = string[*tok++];
199                         j = (*p == '.' ? curenv : 0);
200                         w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0);
201                         *evalTokenBuffer++ = CONST;
202                         uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
203                         *evalTokenBuffer64++ = (TOKEN)w;
204                         evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
205                         break;
206                 case CR_STREQ:
207                         if (*tok != SYMBOL && *tok != STRING)
208                                 return error(str_error);
209
210                         p = string[tok[1]];
211                         tok +=2;
212
213                         if (*tok++ != ',')
214                                 return error(comma_error);
215
216                         if (*tok != SYMBOL && *tok != STRING)
217                                 return error(str_error);
218
219                         p2 = string[tok[1]];
220                         tok += 2;
221
222                         w = (WORD)(!strcmp(p, p2));
223                         *evalTokenBuffer++ = CONST;
224                         evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
225                         *evalTokenBuffer64++ = (TOKEN)w;
226                         evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
227                         break;
228                 }
229         }
230         else
231                 return expr2();
232
233         return OK;
234 }
235
236
237 //
238 // Terminals (CONSTs) and parenthesis grouping
239 //
240 int expr2(void)
241 {
242         char * p;
243         SYM * sy;
244         int j;
245         uint64_t * evalTokenBuffer64;
246         uint64_t * tok64;
247
248         switch ((int)*tok++)
249         {
250         case CONST:
251                 *evalTokenBuffer++ = CONST;
252                 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
253                 tok64 = (uint64_t *)tok;
254                 *evalTokenBuffer64++ = *tok64++;
255                 tok = (TOKEN *)tok64;
256                 evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
257                 break;
258         case FCONST:
259                 *evalTokenBuffer++ = FCONST;
260                 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
261                 tok64 = (uint64_t *)tok;
262                 *evalTokenBuffer64++ = *tok64++;
263                 tok = (TOKEN *)tok64;
264                 evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
265                 break;
266         case SYMBOL:
267                 p = string[*tok++];
268                 j = (*p == '.' ? curenv : 0);
269                 sy = lookup(p, LABEL, j);
270
271                 if (sy == NULL)
272                         sy = NewSymbol(p, LABEL, j);
273
274                 // Check register bank usage
275                 if (sy->sattre & EQUATEDREG)
276                 {
277                         if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
278                                 warn("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
279
280                         if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
281                                 warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
282                 }
283
284                 *evalTokenBuffer++ = SYMBOL;
285                 *evalTokenBuffer++ = symbolNum;
286                 symbolPtr[symbolNum] = sy;
287                 symbolNum++;
288                 break;
289         case STRING:
290                 *evalTokenBuffer++ = CONST;
291                 uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
292                 *evalTokenBuffer64++ = str_value(string[*tok++]);
293                 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
294                 break;
295         case '(':
296                 if (expr0() != OK)
297                         return ERROR;
298
299                 if (*tok++ != ')')
300                         return error("missing closing parenthesis ')'");
301
302                 break;
303         case '[':
304                 if (expr0() != OK)
305                         return ERROR;
306
307                 if (*tok++ != ']')
308                         return error("missing closing bracket ']'");
309
310                 break;
311         case '$':
312                 *evalTokenBuffer++ = ACONST;                            // Attributed const
313                 *evalTokenBuffer++ = sloc;                                      // Current location
314                 *evalTokenBuffer++ = cursect | DEFINED;         // Store attribs
315                 break;
316         case '*':
317                 *evalTokenBuffer++ = ACONST;                            // Attributed const
318
319                 // pcloc == location at start of line
320                 *evalTokenBuffer++ = (orgactive ? orgaddr : pcloc);
321                 // '*' takes attributes of current section, not ABS!
322                 *evalTokenBuffer++ = cursect | DEFINED;
323                 break;
324         case '{':
325                 if (expr0() != OK)                                                      // Eat up first parameter (register or immediate)
326                         return ERROR;
327
328                 if (*tok++ != ':')                                                      // Demand a ':' there
329                         return error("missing colon ':'");
330
331                 if (expr0() != OK)                                                      // Eat up second parameter (register or immediate)
332                         return ERROR;
333
334                 if (*tok++ != '}')
335                         return error("missing closing brace '}'");
336
337                 break;
338         default:
339                 return error("bad expression");
340         }
341
342         return OK;
343 }
344
345
346 //
347 // Recursive-descent expression analyzer (with some simple speed hacks)
348 //
349 int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
350 {
351         // Passed in values (once derefenced, that is) can all be zero. They are
352         // there so that the expression analyzer can fill them in as needed. The
353         // expression analyzer gets its input from the global token pointer "tok",
354         // and not from anything passed in by the user.
355         SYM * symbol;
356         char * p;
357         int j;
358
359         evalTokenBuffer = otk;  // Set token pointer to 'exprbuf' (direct.c)
360                                                         // Also set in various other places too (riscasm.c,
361                                                         // e.g.)
362
363 //printf("expr(): tokens 0-2: %i %i %i (%c %c %c); tc[2] = %i\n", tok[0], tok[1], tok[2], tok[0], tok[1], tok[2], tokenClass[tok[2]]);
364         // Optimize for single constant or single symbol.
365         // Shamus: Subtle bug here. EOL token is 101; if you have a constant token
366         //         followed by the value 101, it will trigger a bad evaluation here.
367         //         This is probably a really bad assumption to be making here...!
368         //         (assuming tok[1] == EOL is a single token that is)
369         //         Seems that even other tokens (SUNARY type) can fuck this up too.
370 //      if ((tok[1] == EOL)
371         if ((tok[1] == EOL && ((tok[0] != CONST || tok[0] != FCONST) && tokenClass[tok[0]] != SUNARY))
372 //              || (((*tok == CONST || *tok == FCONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
373 //              && (tokenClass[tok[2]] < UNARY)))
374                 || (((tok[0] == SYMBOL) || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
375                 && (tokenClass[tok[2]] < UNARY))
376                 || ((tok[0] == CONST || tok[0] == FCONST) && (tokenClass[tok[3]] < UNARY))
377                 )
378         {
379                 if (*tok >= KW_R0 && *tok <= KW_R31)
380                 {
381                         *evalTokenBuffer++ = CONST;
382                         uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
383                         *evalTokenBuffer64++ = *a_value = (*tok - KW_R0);
384                         evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
385                         *a_attr = ABS | DEFINED;
386
387                         if (a_esym != NULL)
388                                 *a_esym = NULL;
389
390                         tok++;
391                 }
392                 else if (*tok == CONST)
393                 {
394                         *evalTokenBuffer++ = CONST;
395                         uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
396                         uint64_t *tok64 = (uint64_t *)&tok[1];
397                         *evalTokenBuffer64++ = *tok64++;
398                         evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
399                         *a_value = tok[1];
400                         *a_attr = ABS | DEFINED;
401
402                         if (a_esym != NULL)
403                                 *a_esym = NULL;
404
405                         tok += 3;
406 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
407                 }
408                 else if (*tok == FCONST)
409                 {
410                         *evalTokenBuffer++ = FCONST;
411                         *((double *)evalTokenBuffer) = *((double *)&tok[1]);
412                         evalTokenBuffer += 2;
413                         //*(double *)evalTokenBuffer++ = tok[2];
414                         *a_value = *((uint64_t *)&tok[1]);
415                         *a_attr = ABS | DEFINED | FLOAT;
416
417                         if (a_esym != NULL)
418                                 *a_esym = NULL;
419
420                         tok += 3;
421 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
422                 }
423                 else if (*tok == '*')
424                 {
425                         *evalTokenBuffer++ = CONST;
426                         uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
427
428                         if (orgactive)
429                                 *evalTokenBuffer64++ = *a_value = orgaddr;
430                         else
431                                 *evalTokenBuffer64++ = *a_value = pcloc;
432                         evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
433
434                         // '*' takes attributes of current section, not ABS!
435                         *a_attr = cursect | DEFINED;
436
437                         if (a_esym != NULL)
438                                 *a_esym = NULL;
439
440                         tok++;
441                 }
442                 else if (*tok == STRING || *tok == SYMBOL)
443                 {
444                         p = string[tok[1]];
445                         j = (*p == '.' ? curenv : 0);
446                         symbol = lookup(p, LABEL, j);
447 #if 0
448 printf("eval: Looking up symbol (%s) [=%08X]\n", p, symbol);
449 if (symbol)
450         printf("      attr=%04X, attre=%08X, val=%i, name=%s\n", symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
451 #endif
452
453                         if (symbol == NULL)
454                                 symbol = NewSymbol(p, LABEL, j);
455
456                         symbol->sattr |= REFERENCED;
457
458                         // Check for undefined register equates, but only if it's not part
459                         // of a #<SYMBOL> construct, as it could be that the label that's
460                         // been undefined may later be used as an address label--which
461                         // means it will be fixed up later, and thus, not an error.
462                         if ((symbol->sattre & UNDEF_EQUR) && !riscImmTokenSeen)
463                         {
464                                 error("undefined register equate '%s'", symbol->sname);
465 //if we return right away, it returns some spurious errors...
466 //                              return ERROR;
467                         }
468
469                         // Check register bank usage
470                         if (symbol->sattre & EQUATEDREG)
471                         {
472                                 if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok)
473                                         warn("equated symbol '%s' cannot be used in register bank 0", symbol->sname);
474
475                                 if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok)
476                                         warn("equated symbol '%s' cannot be used in register bank 1", symbol->sname);
477                         }
478
479                         *evalTokenBuffer++ = SYMBOL;
480 #if 0
481                         *evalTokenBuffer++ = (TOKEN)symbol;
482 #else
483 /*
484 While this approach works, it's wasteful. It would be better to use something
485 that's already available, like the symbol "order defined" table (which needs to
486 be converted from a linked list into an array).
487 */
488                         *evalTokenBuffer++ = symbolNum;
489                         symbolPtr[symbolNum] = symbol;
490                         symbolNum++;
491 #endif
492
493                         if (symbol->sattr & DEFINED)
494                                 *a_value = symbol->svalue;
495                         else
496                                 *a_value = 0;
497
498 /*
499 All that extra crap that was put into the svalue when doing the equr stuff is
500 thrown away right here. What the hell is it for?
501 */
502                         if (symbol->sattre & EQUATEDREG)
503                                 *a_value &= 0x1F;
504
505                         *a_attr = (WORD)(symbol->sattr & ~GLOBAL);
506
507                         if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL
508                                 && a_esym != NULL)
509                                 *a_esym = symbol;
510
511                         tok += 2;
512                 }
513                 else
514                 {
515                         // Unknown type here... Alert the user!,
516                         error("undefined RISC register in expression");
517                         // Prevent spurious error reporting...
518                         tok++;
519                         return ERROR;
520                 }
521
522                 *evalTokenBuffer++ = ENDEXPR;
523                 return OK;
524         }
525
526         if (expr0() != OK)
527                 return ERROR;
528
529         *evalTokenBuffer++ = ENDEXPR;
530         return evexpr(otk, a_value, a_attr, a_esym);
531 }
532
533
534 //
535 // Evaluate expression.
536 // If the expression involves only ONE external symbol, the expression is
537 // UNDEFINED, but it's value includes everything but the symbol value, and
538 // `a_esym' is set to the external symbol.
539 //
540 int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
541 {
542         WORD attr, attr2;
543         SYM * sy;
544         uint64_t * sval = evstk;                                // (Empty) initial stack
545         WORD * sattr = evattr;
546         SYM * esym = NULL;                                              // No external symbol involved
547         WORD sym_seg = 0;
548     uint64_t *tk64;
549
550         while (*tk != ENDEXPR)
551         {
552                 switch ((int)*tk++)
553                 {
554                 case SYMBOL:
555 //printf("evexpr(): SYMBOL\n");
556                         sy = symbolPtr[*tk++];
557                         sy->sattr |= REFERENCED;                // Set "referenced" bit
558
559                         if (!(sy->sattr & DEFINED))
560                         {
561                                 // Reference to undefined symbol
562                                 if (!(sy->sattr & GLOBAL))
563                                 {
564                                         *a_attr = 0;
565                                         *a_value = 0;
566                                         return OK;
567                                 }
568
569                                 if (esym != NULL)                       // Check for multiple externals
570                                         return error(seg_error);
571
572                                 esym = sy;
573                         }
574
575                         if (sy->sattr & DEFINED)
576                         {
577                                 *++sval = sy->svalue;           // Push symbol's value
578                         }
579                         else
580                         {
581                                 *++sval = 0;                            // 0 for undefined symbols
582                         }
583
584                         *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
585                         sym_seg = (WORD)(sy->sattr & TDB);
586                         break;
587                 case CONST:
588                         tk64 = (uint64_t *)tk;
589                         *++sval = *tk64++;
590                         tk = (TOKEN *)tk64;
591 //printf("evexpr(): CONST = %lX\n", *sval);
592                         *++sattr = ABS | DEFINED;               // Push simple attribs
593                         break;
594                 case FCONST:
595 //printf("evexpr(): CONST = %i\n", *tk);
596                         *((double *)sval) = *((double *)tk);
597                         tk += 2;
598                         *++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
599                         break;
600                 case ACONST:
601 //printf("evexpr(): ACONST = %i\n", *tk);
602                         *++sval = *tk++;                                // Push value
603                         *++sattr = (WORD)*tk++;                 // Push attribs
604                         break;
605
606                         // Binary "+" and "-" matrix:
607                         //
608                         //                ABS    Sect     Other
609                         //     ----------------------------
610                         //   ABS     |  ABS   |  Sect  |  Other |
611                         //   Sect    |  Sect  |  [1]   |  Error |
612                         //   Other   |  Other |  Error |  [1]   |
613                         //      ----------------------------
614                         //
615                         //   [1] + : Error
616                         //       - : ABS
617                 case '+':
618 //printf("evexpr(): +\n");
619                         --sval;                                                 // Pop value
620                         --sattr;                                                // Pop attrib
621 //printf("--> N+N: %i + %i = ", *sval, sval[1]);
622                         // Extract float attributes from both terms and pack them
623                         // into a single value
624                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
625                         attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
626
627                         if (attr == (FLOAT | (FLOAT >> 1)))
628                         {
629                                 // Float + Float
630                                 double * dst = (double *)sval;
631                                 double * src = (double *)(sval + 1);
632                                 *dst += *src;
633                         }
634                         else if (attr == FLOAT)
635                         {
636                                 // Float + Int
637                                 double * dst = (double *)sval;
638                                 uint64_t * src = (uint64_t *)(sval + 1);
639                                 *dst += *src;
640                         }
641                         else if (attr == FLOAT >> 1)
642                         {
643                                 // Int + Float
644                                 uint64_t * dst = (uint64_t *)sval;
645                                 double * src = (double *)(sval + 1);
646                                 *(double *)dst = *src + *dst;
647                         }
648                         else
649                         {
650                         *sval += sval[1];                               // Compute value
651                         }
652 //printf("%i\n", *sval);
653
654                         if (!(*sattr & TDB))
655                                 *sattr = sattr[1] | attr2;
656                         else if (sattr[1] & TDB)
657                                 return error(seg_error);
658
659                         break;
660                 case '-':
661 //printf("evexpr(): -\n");
662                         --sval;                                                 // Pop value
663                         --sattr;                                                // Pop attrib
664 //printf("--> N-N: %i - %i = ", *sval, sval[1]);
665                         // Extract float attributes from both terms and pack them
666                         // into a single value
667                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
668                         attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
669
670                         if (attr == (FLOAT | (FLOAT >> 1)))
671                         {
672                                 // Float - Float
673                                 double * dst = (double *)sval;
674                                 double * src = (double *)(sval + 1);
675                                 *dst -= *src;
676                         }
677                         else if (attr == FLOAT)
678                         {
679                                 // Float - Int
680                                 double * dst = (double *)sval;
681                                 uint64_t * src = (uint64_t *)(sval + 1);
682                                 *dst -= *src;
683                         }
684                         else if (attr == FLOAT >> 1)
685                         {
686                                 // Int - Float
687                                 uint64_t * dst = (uint64_t *)sval;
688                                 double * src = (double *)(sval + 1);
689                                 *(double *)dst = *dst - *src;
690                         }
691                         else
692                         {
693                         *sval -= sval[1];                               // Compute value
694                         }
695
696 //printf("%i\n", *sval);
697
698                         attr = (WORD)(*sattr & TDB);
699 #if 0
700 printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
701 #endif
702                         *sattr |= attr2;                // Inherit FLOAT attribute
703                         // If symbol1 is ABS, take attributes from symbol2
704                         if (!attr)
705                                 *sattr = sattr[1];
706                         // Otherwise, they're both TDB and so attributes cancel out
707                         else if (sattr[1] & TDB)
708                                 *sattr &= ~TDB;
709
710                         break;
711                 // Unary operators only work on ABS items
712                 case UNMINUS:
713 //printf("evexpr(): UNMINUS\n");
714                         if (*sattr & TDB)
715                                 return error(seg_error);
716
717                         if (*sattr & FLOAT)
718                         {
719                                 double *dst = (double *)sval;
720                                 *dst = -*dst;
721                                 *sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute
722                         }
723                         else
724                         {
725                         *sval = -(int)*sval;
726                         *sattr = ABS | DEFINED;                 // Expr becomes absolute
727                         }
728                         break;
729                 case '!':
730 //printf("evexpr(): !\n");
731                         if (*sattr & TDB)
732                                 return error(seg_error);
733
734                         if (*sattr & FLOAT)
735                                 return error("floating point numbers not allowed with operator '!'.");
736
737                         *sval = !*sval;
738                         *sattr = ABS | DEFINED;                 // Expr becomes absolute
739                         break;
740                 case '~':
741 //printf("evexpr(): ~\n");
742                         if (*sattr & TDB)
743                                 return error(seg_error);
744
745                         if (*sattr & FLOAT)
746                                 return error("floating point numbers not allowed with operator '~'.");
747
748                         *sval = ~*sval;
749                         *sattr = ABS | DEFINED;                 // Expr becomes absolute
750                         break;
751                 // Comparison operators must have two values that
752                 // are in the same segment, but that's the only requirement.
753                 case LE:
754 //printf("evexpr(): LE\n");
755                         sattr--;
756                         sval--;
757
758                         if ((*sattr & TDB) != (sattr[1] & TDB))
759                                 return error(seg_error);
760
761                         // Extract float attributes from both terms and pack them
762                         // into a single value
763                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
764
765                         if (attr == (FLOAT | (FLOAT >> 1)))
766                         {
767                                 // Float <= Float
768                                 double * dst = (double *)sval;
769                                 double * src = (double *)(sval + 1);
770                                 *sval = *dst <= *src;
771                         }
772                         else if (attr == FLOAT)
773                         {
774                                 // Float <= Int
775                                 double * dst = (double *)sval;
776                                 uint64_t * src = (uint64_t *)(sval + 1);
777                                 *sval = *dst <= *src;
778                         }
779                         else if (attr == FLOAT >> 1)
780                         {
781                                 // Int <= Float
782                                 uint64_t * dst = (uint64_t *)sval;
783                                 double * src = (double *)(sval + 1);
784                                 *sval = *dst <= *src;
785                         }
786                         else
787                         {
788                         *sval = *sval <= sval[1];
789                         }
790
791                         *sattr = ABS | DEFINED;
792                         break;
793                 case GE:
794 //printf("evexpr(): GE\n");
795                         sattr--;
796                         sval--;
797
798                         if ((*sattr & TDB) != (sattr[1] & TDB))
799                                 return error(seg_error);
800
801                         // Extract float attributes from both terms and pack them
802                         // into a single value
803                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
804
805                         if (attr == (FLOAT | (FLOAT >> 1)))
806                         {
807                                 // Float >= Float
808                                 double * dst = (double *)sval;
809                                 double * src = (double *)(sval + 1);
810                                 *sval = *dst >= *src;
811                         }
812                         else if (attr == FLOAT)
813                         {
814                                 // Float >= Int
815                                 double * dst = (double *)sval;
816                                 uint64_t * src = (uint64_t *)(sval + 1);
817                                 *sval = *dst >= *src;
818                         }
819                         else if (attr == FLOAT >> 1)
820                         {
821                                 // Int >= Float
822                                 uint64_t * dst = (uint64_t *)sval;
823                                 double * src = (double *)(sval + 1);
824                                 *sval = *dst >= *src;
825                         }
826                         else if (attr == 0)
827                         {
828                         *sval = *sval >= sval[1];
829                         }
830                         else
831
832                         *sattr = ABS | DEFINED;
833
834                         break;
835                 case '>':
836 //printf("evexpr(): >\n");
837                         sattr--;
838                         sval--;
839
840                         if ((*sattr & TDB) != (sattr[1] & TDB))
841                                 return error(seg_error);
842
843                         // Extract float attributes from both terms and pack them
844                         // into a single value
845                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
846
847                         if (attr == (FLOAT | (FLOAT >> 1)))
848                         {
849                                 // Float > Float
850                                 double * dst = (double *)sval;
851                                 double * src = (double *)(sval + 1);
852                                 *sval = *dst > *src;
853                         }
854                         else if (attr == FLOAT)
855                         {
856                                 // Float > Int
857                                 double * dst = (double *)sval;
858                                 uint64_t * src = (uint64_t *)(sval + 1);
859                                 *sval = *dst > *src;
860                         }
861                         else if (attr == FLOAT >> 1)
862                         {
863                                 // Int > Float
864                                 uint64_t * dst = (uint64_t *)sval;
865                                 double * src = (double *)(sval + 1);
866                                 *sval = *dst > *src;
867                         }
868                         else
869 =                       {
870                         *sval = *sval > sval[1];
871                         }
872
873                         *sattr = ABS | DEFINED;
874
875                         break;
876                 case '<':
877 //printf("evexpr(): <\n");
878                         sattr--;
879                         sval--;
880
881                         if ((*sattr & TDB) != (sattr[1] & TDB))
882                                 return error(seg_error);
883
884                         // Extract float attributes from both terms and pack them
885                         // into a single value
886                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) > >1);
887
888                         if (attr == (FLOAT | (FLOAT >> 1)))
889                         {
890                                 // Float < Float
891                                 double * dst = (double *)sval;
892                                 double * src = (double *)(sval + 1);
893                                 *sval = *dst < *src;
894                         }
895                         else if (attr == FLOAT)
896                         {
897                                 // Float < Int
898                                 double * dst = (double *)sval;
899                                 uint64_t * src = (uint64_t *)(sval + 1);
900                                 *sval = *dst < *src;
901                         }
902                         else if (attr == FLOAT >> 1)
903                         {
904                                 // Int < Float
905                                 uint64_t * dst = (uint64_t *)sval;
906                                 double * src = (double *)(sval + 1);
907                                 *sval = *dst < *src;
908                         }
909                         else
910                         {
911                         *sval = *sval < sval[1];
912                         }
913
914                         *sattr = ABS | DEFINED;
915
916                         break;
917                 case NE:
918 //printf("evexpr(): NE\n");
919                         sattr--;
920                         sval--;
921
922                         if ((*sattr & TDB) != (sattr[1] & TDB))
923                                 return error(seg_error);
924
925                         // Extract float attributes from both terms and pack them
926                         // into a single value
927                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
928
929                         if (attr == (FLOAT | (FLOAT >> 1)))
930                         {
931                                 // Float <> Float
932                                 return error("comparison for equality with float types not allowed.");
933                         }
934                         else if (attr == FLOAT)
935                         {
936                                 // Float <> Int
937                                 return error("comparison for equality with float types not allowed.");
938                         }
939                         else if (attr == FLOAT >> 1)
940                         {
941                                 // Int != Float
942                                 return error("comparison for equality with float types not allowed.");
943                         }
944                         else
945                         {
946                         *sval = *sval != sval[1];
947                         }
948
949                         *sattr = ABS | DEFINED;
950
951                         break;
952                 case '=':
953 //printf("evexpr(): =\n");
954                         sattr--;
955                         sval--;
956
957                         if ((*sattr & TDB) != (sattr[1] & TDB))
958                                 return error(seg_error);
959
960                         // Extract float attributes from both terms and pack them
961                         // into a single value
962                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
963
964                         if (attr == (FLOAT | (FLOAT >> 1)))
965                         {
966                                 // Float = Float
967                                 double * dst = (double *)sval;
968                                 double * src = (double *)(sval + 1);
969                                 *sval = *src == *dst;
970                         }
971                         else if (attr == FLOAT)
972                         {
973                                 // Float = Int
974                                 return error("equality with float ");
975                         }
976                         else if (attr == FLOAT >> 1)
977                         {
978                                 // Int == Float
979                                 uint64_t * dst = (uint64_t *)sval;
980                                 double * src = (double *)(sval + 1);
981                                 *sval = *src == *dst;
982                         }
983                         else
984                         {
985                         *sval = *sval == sval[1];
986                         }
987
988                         *sattr = ABS | DEFINED;
989
990                         break;
991                 // All other binary operators must have two ABS items
992                 // to work with.  They all produce an ABS value.
993                 default:
994 //printf("evexpr(): default\n");
995                         // GH - Removed for v1.0.15 as part of the fix for indexed loads.
996                         //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
997                         //error(seg_error);
998
999                         switch ((int)tk[-1])
1000                         {
1001                         case '*':
1002                                 sval--;
1003                                 sattr--;                                        // Pop attrib
1004 //printf("--> NxN: %i x %i = ", *sval, sval[1]);
1005                                 // Extract float attributes from both terms and pack them
1006                                 // into a single value
1007                                 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
1008                                 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
1009
1010                                 if (attr == (FLOAT | (FLOAT >> 1)))
1011                                 {
1012                                         // Float * Float
1013                                         double * dst = (double *)sval;
1014                                         double * src = (double *)(sval + 1);
1015                                         *dst *= *src;
1016                                 }
1017                                 else if (attr == FLOAT)
1018                                 {
1019                                         // Float * Int
1020                                         double * dst = (double *)sval;
1021                                         uint64_t * src = (uint64_t *)(sval + 1);
1022                                         *dst *= *src;
1023                                 }
1024                                 else if (attr == FLOAT >> 1)
1025                                 {
1026                                         // Int * Float
1027                                         uint64_t * dst = (uint64_t *)sval;
1028                                         double * src = (double *)(sval + 1);
1029                                         *(double *)dst = *src * *dst;
1030                                 }
1031                                 else
1032                                 {
1033                                 *sval *= sval[1];
1034                                 }
1035 //printf("%i\n", *sval);
1036
1037                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1038                                 *sattr |= attr2;
1039
1040                                 break;
1041                         case '/':
1042                                 sval--;
1043                                 sattr--;                                        // Pop attrib
1044
1045
1046 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1047                                 // Extract float attributes from both terms and pack them
1048                                 // into a single value
1049                                 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
1050                                 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
1051
1052                                 if (attr == (FLOAT | (FLOAT >> 1)))
1053                                 {
1054                                         // Float / Float
1055                                         double * dst = (double *)sval;
1056                                         double * src = (double *)(sval + 1);
1057                                         if (*src == 0)
1058                                                 return error("divide by zero");
1059                                         *dst = *dst / *src;
1060                                 }
1061                                 else if (attr == FLOAT)
1062                                 {
1063                                         // Float / Int
1064                                         double * dst = (double *)sval;
1065                                         uint64_t * src = (uint64_t *)(sval + 1);
1066                                         if (*src == 0)
1067                                                 return error("divide by zero");
1068                                         *dst = *dst / *src;
1069                                 }
1070                                 else if (attr == FLOAT >> 1)
1071                                 {
1072                                         // Int / Float
1073                                         uint64_t * dst=(uint64_t *)sval;
1074                                         double * src=(double *)(sval + 1);
1075                                         if (*src == 0)
1076                                                 return error("divide by zero");
1077                                         *(double *)dst = *dst / *src;
1078                                 }
1079                                 else
1080                                 {
1081                                         if (sval[1] == 0)
1082                                                 return error("divide by zero");
1083 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1084                                 // Compiler is picky here: Without casting these, it discards
1085                                 // the sign if dividing a negative # by a positive one,
1086                                 // creating a bad result. :-/
1087                                 // Definitely a side effect of using uint32_ts intead of ints.
1088                                 *sval = (int32_t)sval[0] / (int32_t)sval[1];
1089                                 }
1090
1091                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1092                                 *sattr |= attr2;
1093
1094 //printf("%i\n", *sval);
1095                                 break;
1096                         case '%':
1097                                 sval--;
1098                                 sattr--;                                        // Pop attrib
1099                                 if ((*sattr | sattr[1]) & FLOAT)
1100                                         return error("floating point numbers not allowed with operator '%'.");
1101
1102                                 if (sval[1] == 0)
1103                                         return error("mod (%) by zero");
1104
1105                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1106                                 *sval %= sval[1];
1107                                 break;
1108                         case SHL:
1109                                 sval--;
1110                                 sattr--;                                        // Pop attrib
1111                                 if ((*sattr | sattr[1]) & FLOAT)
1112                                         return error("floating point numbers not allowed with operator '<<'.");
1113                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1114                                 *sval <<= sval[1];
1115                                 break;
1116                         case SHR:
1117                                 sval--;
1118                                 sattr--;                                        // Pop attrib
1119                                 if ((*sattr | sattr[1]) & FLOAT)
1120                                         return error("floating point numbers not allowed with operator '>>'.");
1121                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1122                                 *sval >>= sval[1];
1123                                 break;
1124                         case '&':
1125                                 sval--;
1126                                 sattr--;                                        // Pop attrib
1127                                 if ((*sattr | sattr[1]) & FLOAT)
1128                                         return error("floating point numbers not allowed with operator '&'.");
1129                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1130                                 *sval &= sval[1];
1131                                 break;
1132                         case '^':
1133                                 sval--;
1134                                 sattr--;                                        // Pop attrib
1135                                 if ((*sattr | sattr[1]) & FLOAT)
1136                                         return error("floating point numbers not allowed with operator '^'.");
1137                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1138                                 *sval ^= sval[1];
1139                                 break;
1140                         case '|':
1141                                 sval--;
1142                                 sattr--;                                        // Pop attrib
1143                                 if ((*sattr | sattr[1]) & FLOAT)
1144                                         return error("floating point numbers not allowed with operator '|'.");
1145                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1146                                 *sval |= sval[1];
1147                                 break;
1148                         default:
1149                                 interror(5);                            // Bad operator in expression stream
1150                         }
1151                 }
1152         }
1153
1154         if (esym != NULL)
1155                 *sattr &= ~DEFINED;
1156
1157         if (a_esym != NULL)
1158                 *a_esym = esym;
1159
1160         // sym_seg added in 1.0.16 to solve a problem with forward symbols in
1161         // expressions where absolute values also existed. The absolutes were
1162         // overiding the symbol segments and not being included :(
1163         //*a_attr = *sattr | sym_seg;           // Copy value + attrib
1164
1165         *a_attr = *sattr;                                               // Copy value + attrib
1166         *a_value = *sval;
1167
1168         return OK;
1169 }
1170