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