blob: a75c5baef6d16c8231274fab5e1aa48e380da341 [file] [log] [blame]
H. Peter Anvin76690a12002-04-30 20:52:49 +00001/* eval.c expression evaluator for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
8 * initial version 27/iii/95 by Simon Tatham
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <stddef.h>
14#include <string.h>
15#include <ctype.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000016#include <inttypes.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000017
18#include "nasm.h"
19#include "nasmlib.h"
20#include "eval.h"
H. Peter Anvineba20a72002-04-30 20:53:55 +000021#include "labels.h"
H. Peter Anvindc467ba2007-09-24 12:30:54 -070022#include "float.h"
H. Peter Anvin76690a12002-04-30 20:52:49 +000023
H. Peter Anvin76690a12002-04-30 20:52:49 +000024#define TEMPEXPRS_DELTA 128
H. Peter Anvin76690a12002-04-30 20:52:49 +000025#define TEMPEXPR_DELTA 8
26
H. Peter Anvine2c80182005-01-15 22:15:51 +000027static scanner scan; /* Address of scanner routine */
28static efunc error; /* Address of error reporting routine */
29static lfunc labelfunc; /* Address of label routine */
H. Peter Anvineba20a72002-04-30 20:53:55 +000030
H. Peter Anvine2c80182005-01-15 22:15:51 +000031static struct ofmt *outfmt; /* Structure of addresses of output routines */
H. Peter Anvineba20a72002-04-30 20:53:55 +000032
33static expr **tempexprs = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +000034static int ntempexprs;
35static int tempexprs_size = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +000036
H. Peter Anvine2c80182005-01-15 22:15:51 +000037static expr *tempexpr;
38static int ntempexpr;
39static int tempexpr_size;
H. Peter Anvineba20a72002-04-30 20:53:55 +000040
H. Peter Anvine2c80182005-01-15 22:15:51 +000041static struct tokenval *tokval; /* The current token */
42static int i; /* The t_type of tokval */
H. Peter Anvineba20a72002-04-30 20:53:55 +000043
H. Peter Anvin76690a12002-04-30 20:52:49 +000044static void *scpriv;
H. Peter Anvine2c80182005-01-15 22:15:51 +000045static loc_t *location; /* Pointer to current line's segment,offset */
H. Peter Anvineba20a72002-04-30 20:53:55 +000046static int *opflags;
H. Peter Anvin76690a12002-04-30 20:52:49 +000047
48static struct eval_hints *hint;
49
H. Peter Anvine2c80182005-01-15 22:15:51 +000050extern int in_abs_seg; /* ABSOLUTE segment flag */
Keith Kaniosb7a89542007-04-12 02:40:54 +000051extern int32_t abs_seg; /* ABSOLUTE segment */
52extern int32_t abs_offset; /* ABSOLUTE segment offset */
H. Peter Anvin667dd802002-05-26 19:49:41 +000053
H. Peter Anvin76690a12002-04-30 20:52:49 +000054/*
H. Peter Anvineba20a72002-04-30 20:53:55 +000055 * Unimportant cleanup is done to avoid confusing people who are trying
56 * to debug real memory leaks
57 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000058void eval_cleanup(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +000059{
60 while (ntempexprs)
H. Peter Anvine2c80182005-01-15 22:15:51 +000061 nasm_free(tempexprs[--ntempexprs]);
62 nasm_free(tempexprs);
H. Peter Anvineba20a72002-04-30 20:53:55 +000063}
64
65/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000066 * Construct a temporary expression.
67 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000068static void begintemp(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +000069{
H. Peter Anvin76690a12002-04-30 20:52:49 +000070 tempexpr = NULL;
71 tempexpr_size = ntempexpr = 0;
72}
73
Keith Kaniosb7a89542007-04-12 02:40:54 +000074static void addtotemp(int32_t type, int64_t value)
H. Peter Anvineba20a72002-04-30 20:53:55 +000075{
H. Peter Anvin76690a12002-04-30 20:52:49 +000076 while (ntempexpr >= tempexpr_size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +000077 tempexpr_size += TEMPEXPR_DELTA;
78 tempexpr = nasm_realloc(tempexpr,
79 tempexpr_size * sizeof(*tempexpr));
H. Peter Anvin76690a12002-04-30 20:52:49 +000080 }
81 tempexpr[ntempexpr].type = type;
82 tempexpr[ntempexpr++].value = value;
83}
84
H. Peter Anvine2c80182005-01-15 22:15:51 +000085static expr *finishtemp(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +000086{
H. Peter Anvine2c80182005-01-15 22:15:51 +000087 addtotemp(0L, 0L); /* terminate */
H. Peter Anvin76690a12002-04-30 20:52:49 +000088 while (ntempexprs >= tempexprs_size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +000089 tempexprs_size += TEMPEXPRS_DELTA;
90 tempexprs = nasm_realloc(tempexprs,
91 tempexprs_size * sizeof(*tempexprs));
H. Peter Anvin76690a12002-04-30 20:52:49 +000092 }
93 return tempexprs[ntempexprs++] = tempexpr;
94}
95
96/*
97 * Add two vector datatypes. We have some bizarre behaviour on far-
98 * absolute segment types: we preserve them during addition _only_
99 * if one of the segments is a truly pure scalar.
100 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000101static expr *add_vectors(expr * p, expr * q)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000102{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000103 int preserve;
104
105 preserve = is_really_simple(p) || is_really_simple(q);
106
107 begintemp();
108
109 while (p->type && q->type &&
H. Peter Anvine2c80182005-01-15 22:15:51 +0000110 p->type < EXPR_SEGBASE + SEG_ABS &&
111 q->type < EXPR_SEGBASE + SEG_ABS) {
112 int lasttype;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000113
H. Peter Anvine2c80182005-01-15 22:15:51 +0000114 if (p->type > q->type) {
115 addtotemp(q->type, q->value);
116 lasttype = q++->type;
117 } else if (p->type < q->type) {
118 addtotemp(p->type, p->value);
119 lasttype = p++->type;
120 } else { /* *p and *q have same type */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000121 int32_t sum = p->value + q->value;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000122 if (sum)
123 addtotemp(p->type, sum);
124 lasttype = p->type;
125 p++, q++;
126 }
127 if (lasttype == EXPR_UNKNOWN) {
128 return finishtemp();
129 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000130 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000131 while (p->type && (preserve || p->type < EXPR_SEGBASE + SEG_ABS)) {
132 addtotemp(p->type, p->value);
133 p++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000134 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000135 while (q->type && (preserve || q->type < EXPR_SEGBASE + SEG_ABS)) {
136 addtotemp(q->type, q->value);
137 q++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000138 }
139
140 return finishtemp();
141}
142
143/*
144 * Multiply a vector by a scalar. Strip far-absolute segment part
145 * if present.
146 *
147 * Explicit treatment of UNKNOWN is not required in this routine,
148 * since it will silently do the Right Thing anyway.
149 *
150 * If `affect_hints' is set, we also change the hint type to
151 * NOTBASE if a MAKEBASE hint points at a register being
152 * multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
153 * as the base register.
154 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000155static expr *scalar_mult(expr * vect, int32_t scalar, int affect_hints)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000156{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000157 expr *p = vect;
158
H. Peter Anvine2c80182005-01-15 22:15:51 +0000159 while (p->type && p->type < EXPR_SEGBASE + SEG_ABS) {
160 p->value = scalar * (p->value);
161 if (hint && hint->type == EAH_MAKEBASE &&
162 p->type == hint->base && affect_hints)
163 hint->type = EAH_NOTBASE;
164 p++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000165 }
166 p->type = 0;
167
168 return vect;
169}
170
Keith Kaniosb7a89542007-04-12 02:40:54 +0000171static expr *scalarvect(int32_t scalar)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000172{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000173 begintemp();
174 addtotemp(EXPR_SIMPLE, scalar);
175 return finishtemp();
176}
177
H. Peter Anvine2c80182005-01-15 22:15:51 +0000178static expr *unknown_expr(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000179{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000180 begintemp();
181 addtotemp(EXPR_UNKNOWN, 1L);
182 return finishtemp();
183}
184
185/*
186 * The SEG operator: calculate the segment part of a relocatable
187 * value. Return NULL, as usual, if an error occurs. Report the
188 * error too.
189 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000190static expr *segment_part(expr * e)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000191{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000192 int32_t seg;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000193
194 if (is_unknown(e))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000195 return unknown_expr();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000196
197 if (!is_reloc(e)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000198 error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
199 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000200 }
201
202 seg = reloc_seg(e);
203 if (seg == NO_SEG) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000204 error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
205 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000206 } else if (seg & SEG_ABS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000207 return scalarvect(seg & ~SEG_ABS);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000208 } else if (seg & 1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000209 error(ERR_NONFATAL, "SEG applied to something which"
210 " is already a segment base");
211 return NULL;
212 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000213 int32_t base = outfmt->segbase(seg + 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000214
H. Peter Anvine2c80182005-01-15 22:15:51 +0000215 begintemp();
216 addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE + base),
217 1L);
218 return finishtemp();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000219 }
220}
221
222/*
223 * Recursive-descent parser. Called with a single boolean operand,
224 * which is TRUE if the evaluation is critical (i.e. unresolved
225 * symbols are an error condition). Must update the global `i' to
226 * reflect the token after the parsed string. May return NULL.
227 *
228 * evaluate() should report its own errors: on return it is assumed
229 * that if NULL has been returned, the error has already been
230 * reported.
231 */
232
233/*
234 * Grammar parsed is:
235 *
236 * expr : bexpr [ WRT expr6 ]
237 * bexpr : rexp0 or expr0 depending on relative-mode setting
238 * rexp0 : rexp1 [ {||} rexp1...]
239 * rexp1 : rexp2 [ {^^} rexp2...]
240 * rexp2 : rexp3 [ {&&} rexp3...]
241 * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=} expr0 ]
242 * expr0 : expr1 [ {|} expr1...]
243 * expr1 : expr2 [ {^} expr2...]
244 * expr2 : expr3 [ {&} expr3...]
245 * expr3 : expr4 [ {<<,>>} expr4...]
246 * expr4 : expr5 [ {+,-} expr5...]
247 * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
248 * expr6 : { ~,+,-,SEG } expr6
249 * | (bexpr)
250 * | symbol
251 * | $
252 * | number
253 */
254
255static expr *rexp0(int), *rexp1(int), *rexp2(int), *rexp3(int);
256
257static expr *expr0(int), *expr1(int), *expr2(int), *expr3(int);
258static expr *expr4(int), *expr5(int), *expr6(int);
259
H. Peter Anvine2c80182005-01-15 22:15:51 +0000260static expr *(*bexpr) (int);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000261
H. Peter Anvine2c80182005-01-15 22:15:51 +0000262static expr *rexp0(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000263{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000264 expr *e, *f;
265
266 e = rexp1(critical);
267 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000268 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000269
H. Peter Anvine2c80182005-01-15 22:15:51 +0000270 while (i == TOKEN_DBL_OR) {
271 i = scan(scpriv, tokval);
272 f = rexp1(critical);
273 if (!f)
274 return NULL;
275 if (!(is_simple(e) || is_just_unknown(e)) ||
276 !(is_simple(f) || is_just_unknown(f))) {
277 error(ERR_NONFATAL, "`|' operator may only be applied to"
278 " scalar values");
279 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000280
H. Peter Anvine2c80182005-01-15 22:15:51 +0000281 if (is_just_unknown(e) || is_just_unknown(f))
282 e = unknown_expr();
283 else
Keith Kaniosb7a89542007-04-12 02:40:54 +0000284 e = scalarvect((int32_t)(reloc_value(e) || reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000285 }
286 return e;
287}
288
H. Peter Anvine2c80182005-01-15 22:15:51 +0000289static expr *rexp1(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000290{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000291 expr *e, *f;
292
293 e = rexp2(critical);
294 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000295 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000296
H. Peter Anvine2c80182005-01-15 22:15:51 +0000297 while (i == TOKEN_DBL_XOR) {
298 i = scan(scpriv, tokval);
299 f = rexp2(critical);
300 if (!f)
301 return NULL;
302 if (!(is_simple(e) || is_just_unknown(e)) ||
303 !(is_simple(f) || is_just_unknown(f))) {
304 error(ERR_NONFATAL, "`^' operator may only be applied to"
305 " scalar values");
306 }
307
308 if (is_just_unknown(e) || is_just_unknown(f))
309 e = unknown_expr();
310 else
Keith Kaniosb7a89542007-04-12 02:40:54 +0000311 e = scalarvect((int32_t)(!reloc_value(e) ^ !reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000312 }
313 return e;
314}
315
H. Peter Anvine2c80182005-01-15 22:15:51 +0000316static expr *rexp2(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000317{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000318 expr *e, *f;
319
320 e = rexp3(critical);
321 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000322 return NULL;
323 while (i == TOKEN_DBL_AND) {
324 i = scan(scpriv, tokval);
325 f = rexp3(critical);
326 if (!f)
327 return NULL;
328 if (!(is_simple(e) || is_just_unknown(e)) ||
329 !(is_simple(f) || is_just_unknown(f))) {
330 error(ERR_NONFATAL, "`&' operator may only be applied to"
331 " scalar values");
332 }
333 if (is_just_unknown(e) || is_just_unknown(f))
334 e = unknown_expr();
335 else
Keith Kaniosb7a89542007-04-12 02:40:54 +0000336 e = scalarvect((int32_t)(reloc_value(e) && reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000337 }
338 return e;
339}
340
H. Peter Anvine2c80182005-01-15 22:15:51 +0000341static expr *rexp3(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000342{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000343 expr *e, *f;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000344 int32_t v;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000345
346 e = expr0(critical);
347 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000348 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000349
H. Peter Anvin76690a12002-04-30 20:52:49 +0000350 while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000351 i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE) {
352 int j = i;
353 i = scan(scpriv, tokval);
354 f = expr0(critical);
355 if (!f)
356 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000357
H. Peter Anvine2c80182005-01-15 22:15:51 +0000358 e = add_vectors(e, scalar_mult(f, -1L, FALSE));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000359
H. Peter Anvine2c80182005-01-15 22:15:51 +0000360 switch (j) {
361 case TOKEN_EQ:
362 case TOKEN_NE:
363 if (is_unknown(e))
364 v = -1; /* means unknown */
365 else if (!is_really_simple(e) || reloc_value(e) != 0)
366 v = (j == TOKEN_NE); /* unequal, so return TRUE if NE */
367 else
368 v = (j == TOKEN_EQ); /* equal, so return TRUE if EQ */
369 break;
370 default:
371 if (is_unknown(e))
372 v = -1; /* means unknown */
373 else if (!is_really_simple(e)) {
374 error(ERR_NONFATAL,
375 "`%s': operands differ by a non-scalar",
376 (j == TOKEN_LE ? "<=" : j == TOKEN_LT ? "<" : j ==
377 TOKEN_GE ? ">=" : ">"));
378 v = 0; /* must set it to _something_ */
379 } else {
380 int vv = reloc_value(e);
381 if (vv == 0)
382 v = (j == TOKEN_LE || j == TOKEN_GE);
383 else if (vv > 0)
384 v = (j == TOKEN_GE || j == TOKEN_GT);
385 else /* vv < 0 */
386 v = (j == TOKEN_LE || j == TOKEN_LT);
387 }
388 break;
389 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000390
H. Peter Anvine2c80182005-01-15 22:15:51 +0000391 if (v == -1)
392 e = unknown_expr();
393 else
394 e = scalarvect(v);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000395 }
396 return e;
397}
398
H. Peter Anvine2c80182005-01-15 22:15:51 +0000399static expr *expr0(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000400{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000401 expr *e, *f;
402
403 e = expr1(critical);
404 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000405 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000406
H. Peter Anvine2c80182005-01-15 22:15:51 +0000407 while (i == '|') {
408 i = scan(scpriv, tokval);
409 f = expr1(critical);
410 if (!f)
411 return NULL;
412 if (!(is_simple(e) || is_just_unknown(e)) ||
413 !(is_simple(f) || is_just_unknown(f))) {
414 error(ERR_NONFATAL, "`|' operator may only be applied to"
415 " scalar values");
416 }
417 if (is_just_unknown(e) || is_just_unknown(f))
418 e = unknown_expr();
419 else
420 e = scalarvect(reloc_value(e) | reloc_value(f));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000421 }
422 return e;
423}
424
H. Peter Anvine2c80182005-01-15 22:15:51 +0000425static expr *expr1(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000426{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000427 expr *e, *f;
428
429 e = expr2(critical);
430 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000431 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000432
H. Peter Anvin76690a12002-04-30 20:52:49 +0000433 while (i == '^') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000434 i = scan(scpriv, tokval);
435 f = expr2(critical);
436 if (!f)
437 return NULL;
438 if (!(is_simple(e) || is_just_unknown(e)) ||
439 !(is_simple(f) || is_just_unknown(f))) {
440 error(ERR_NONFATAL, "`^' operator may only be applied to"
441 " scalar values");
442 }
443 if (is_just_unknown(e) || is_just_unknown(f))
444 e = unknown_expr();
445 else
446 e = scalarvect(reloc_value(e) ^ reloc_value(f));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000447 }
448 return e;
449}
450
H. Peter Anvine2c80182005-01-15 22:15:51 +0000451static expr *expr2(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000452{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000453 expr *e, *f;
454
455 e = expr3(critical);
456 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000457 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000458
H. Peter Anvin76690a12002-04-30 20:52:49 +0000459 while (i == '&') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000460 i = scan(scpriv, tokval);
461 f = expr3(critical);
462 if (!f)
463 return NULL;
464 if (!(is_simple(e) || is_just_unknown(e)) ||
465 !(is_simple(f) || is_just_unknown(f))) {
466 error(ERR_NONFATAL, "`&' operator may only be applied to"
467 " scalar values");
468 }
469 if (is_just_unknown(e) || is_just_unknown(f))
470 e = unknown_expr();
471 else
472 e = scalarvect(reloc_value(e) & reloc_value(f));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000473 }
474 return e;
475}
476
H. Peter Anvine2c80182005-01-15 22:15:51 +0000477static expr *expr3(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000478{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000479 expr *e, *f;
480
481 e = expr4(critical);
482 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000483 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000484
H. Peter Anvine2c80182005-01-15 22:15:51 +0000485 while (i == TOKEN_SHL || i == TOKEN_SHR) {
486 int j = i;
487 i = scan(scpriv, tokval);
488 f = expr4(critical);
489 if (!f)
490 return NULL;
491 if (!(is_simple(e) || is_just_unknown(e)) ||
492 !(is_simple(f) || is_just_unknown(f))) {
493 error(ERR_NONFATAL, "shift operator may only be applied to"
494 " scalar values");
495 } else if (is_just_unknown(e) || is_just_unknown(f)) {
496 e = unknown_expr();
497 } else
498 switch (j) {
499 case TOKEN_SHL:
500 e = scalarvect(reloc_value(e) << reloc_value(f));
501 break;
502 case TOKEN_SHR:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000503 e = scalarvect(((uint32_t)reloc_value(e)) >>
H. Peter Anvine2c80182005-01-15 22:15:51 +0000504 reloc_value(f));
505 break;
506 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000507 }
508 return e;
509}
510
H. Peter Anvine2c80182005-01-15 22:15:51 +0000511static expr *expr4(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000512{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000513 expr *e, *f;
514
515 e = expr5(critical);
516 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000517 return NULL;
518 while (i == '+' || i == '-') {
519 int j = i;
520 i = scan(scpriv, tokval);
521 f = expr5(critical);
522 if (!f)
523 return NULL;
524 switch (j) {
525 case '+':
526 e = add_vectors(e, f);
527 break;
528 case '-':
529 e = add_vectors(e, scalar_mult(f, -1L, FALSE));
530 break;
531 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000532 }
533 return e;
534}
535
H. Peter Anvine2c80182005-01-15 22:15:51 +0000536static expr *expr5(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000537{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000538 expr *e, *f;
539
540 e = expr6(critical);
541 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000542 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000543 while (i == '*' || i == '/' || i == '%' ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000544 i == TOKEN_SDIV || i == TOKEN_SMOD) {
545 int j = i;
546 i = scan(scpriv, tokval);
547 f = expr6(critical);
548 if (!f)
549 return NULL;
550 if (j != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
551 !(is_simple(f) || is_just_unknown(f)))) {
552 error(ERR_NONFATAL, "division operator may only be applied to"
553 " scalar values");
554 return NULL;
555 }
556 if (j != '*' && !is_unknown(f) && reloc_value(f) == 0) {
557 error(ERR_NONFATAL, "division by zero");
558 return NULL;
559 }
560 switch (j) {
561 case '*':
562 if (is_simple(e))
563 e = scalar_mult(f, reloc_value(e), TRUE);
564 else if (is_simple(f))
565 e = scalar_mult(e, reloc_value(f), TRUE);
566 else if (is_just_unknown(e) && is_just_unknown(f))
567 e = unknown_expr();
568 else {
569 error(ERR_NONFATAL, "unable to multiply two "
570 "non-scalar objects");
571 return NULL;
572 }
573 break;
574 case '/':
575 if (is_just_unknown(e) || is_just_unknown(f))
576 e = unknown_expr();
577 else
Keith Kaniosb7a89542007-04-12 02:40:54 +0000578 e = scalarvect(((uint32_t)reloc_value(e)) /
579 ((uint32_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000580 break;
581 case '%':
582 if (is_just_unknown(e) || is_just_unknown(f))
583 e = unknown_expr();
584 else
Keith Kaniosb7a89542007-04-12 02:40:54 +0000585 e = scalarvect(((uint32_t)reloc_value(e)) %
586 ((uint32_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000587 break;
588 case TOKEN_SDIV:
589 if (is_just_unknown(e) || is_just_unknown(f))
590 e = unknown_expr();
591 else
Keith Kaniosb7a89542007-04-12 02:40:54 +0000592 e = scalarvect(((int32_t)reloc_value(e)) /
593 ((int32_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000594 break;
595 case TOKEN_SMOD:
596 if (is_just_unknown(e) || is_just_unknown(f))
597 e = unknown_expr();
598 else
Keith Kaniosb7a89542007-04-12 02:40:54 +0000599 e = scalarvect(((int32_t)reloc_value(e)) %
600 ((int32_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000601 break;
602 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000603 }
604 return e;
605}
606
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700607static expr *eval_floatize(enum floatize type)
608{
609 uint8_t result[16], *p; /* Up to 128 bits */
610 static const struct {
611 int bytes, start, len;
612 } formats[] = {
613 { 2, 0, 2 }, /* FLOAT_16 */
614 { 4, 0, 4 }, /* FLOAT_32 */
615 { 8, 0, 8 }, /* FLOAT_64 */
616 { 10, 0, 8 }, /* FLOAT_80M */
617 { 10, 8, 2 }, /* FLOAT_80E */
618 { 16, 0, 8 }, /* FLOAT_128L */
619 { 16, 8, 8 }, /* FLOAT_128H */
620 };
621 int sign = 1;
622 int64_t val;
623 int j;
624
625 i = scan(scpriv, tokval);
626 if (i != '(') {
627 error(ERR_NONFATAL, "expecting `('");
628 return NULL;
629 }
630 i = scan(scpriv, tokval);
631 if (i == '-' || i == '+') {
632 sign = (i == '-') ? -1 : 1;
633 i = scan(scpriv, tokval);
634 }
635 if (i != TOKEN_FLOAT) {
636 error(ERR_NONFATAL, "expecting floating-point number");
637 return NULL;
638 }
639 if (!float_const(tokval->t_charptr, sign, result,
640 formats[type].bytes, error))
641 return NULL;
642 i = scan(scpriv, tokval);
643 if (i != ')') {
644 error(ERR_NONFATAL, "expecting `)'");
645 return NULL;
646 }
647
648 p = result+formats[type].start+formats[type].len;
649 val = 0;
650 for (j = formats[type].len; j; j--) {
651 p--;
652 val = (val << 8) + *p;
653 }
654
655 begintemp();
656 addtotemp(EXPR_SIMPLE, val);
657
658 i = scan(scpriv, tokval);
659 return finishtemp();
660}
661
H. Peter Anvine2c80182005-01-15 22:15:51 +0000662static expr *expr6(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000663{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000664 int32_t type;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000665 expr *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000666 int32_t label_seg, label_ofs;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000667
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700668 switch (i) {
669 case '-':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000670 i = scan(scpriv, tokval);
671 e = expr6(critical);
672 if (!e)
673 return NULL;
674 return scalar_mult(e, -1L, FALSE);
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700675
676
677 case '+':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000678 i = scan(scpriv, tokval);
679 return expr6(critical);
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700680
681 case '~':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000682 i = scan(scpriv, tokval);
683 e = expr6(critical);
684 if (!e)
685 return NULL;
686 if (is_just_unknown(e))
687 return unknown_expr();
688 else if (!is_simple(e)) {
689 error(ERR_NONFATAL, "`~' operator may only be applied to"
690 " scalar values");
691 return NULL;
692 }
693 return scalarvect(~reloc_value(e));
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700694
695 case '!':
Chuck Craynecb9bc212007-05-02 04:21:26 +0000696 i = scan(scpriv, tokval);
697 e = expr6(critical);
698 if (!e)
699 return NULL;
700 if (is_just_unknown(e))
701 return unknown_expr();
702 else if (!is_simple(e)) {
703 error(ERR_NONFATAL, "`!' operator may only be applied to"
704 " scalar values");
705 return NULL;
706 }
707 return scalarvect(!reloc_value(e));
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700708
709 case TOKEN_SEG:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000710 i = scan(scpriv, tokval);
711 e = expr6(critical);
712 if (!e)
713 return NULL;
714 e = segment_part(e);
715 if (!e)
716 return NULL;
717 if (is_unknown(e) && critical) {
718 error(ERR_NONFATAL, "unable to determine segment base");
719 return NULL;
720 }
721 return e;
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700722
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700723 case TOKEN_FLOATIZE:
724 return eval_floatize(tokval->t_integer);
725
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700726 case '(':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000727 i = scan(scpriv, tokval);
728 e = bexpr(critical);
729 if (!e)
730 return NULL;
731 if (i != ')') {
732 error(ERR_NONFATAL, "expecting `)'");
733 return NULL;
734 }
735 i = scan(scpriv, tokval);
736 return e;
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700737
738 case TOKEN_NUM:
739 case TOKEN_REG:
740 case TOKEN_ID:
741 case TOKEN_HERE:
742 case TOKEN_BASE:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000743 begintemp();
744 switch (i) {
745 case TOKEN_NUM:
746 addtotemp(EXPR_SIMPLE, tokval->t_integer);
747 break;
748 case TOKEN_REG:
749 addtotemp(tokval->t_integer, 1L);
750 if (hint && hint->type == EAH_NOHINT)
751 hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
752 break;
753 case TOKEN_ID:
754 case TOKEN_HERE:
755 case TOKEN_BASE:
756 /*
757 * If !location->known, this indicates that no
758 * symbol, Here or Base references are valid because we
759 * are in preprocess-only mode.
760 */
761 if (!location->known) {
762 error(ERR_NONFATAL,
763 "%s not supported in preprocess-only mode",
764 (i == TOKEN_ID ? "symbol references" :
765 i == TOKEN_HERE ? "`$'" : "`$$'"));
766 addtotemp(EXPR_UNKNOWN, 1L);
767 break;
768 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000769
H. Peter Anvine2c80182005-01-15 22:15:51 +0000770 type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
771 if (i == TOKEN_BASE) {
772 label_seg = in_abs_seg ? abs_seg : location->segment;
773 label_ofs = 0;
774 } else if (i == TOKEN_HERE) {
775 label_seg = in_abs_seg ? abs_seg : location->segment;
776 label_ofs = in_abs_seg ? abs_offset : location->offset;
777 } else {
778 if (!labelfunc(tokval->t_charptr, &label_seg, &label_ofs)) {
779 if (critical == 2) {
780 error(ERR_NONFATAL, "symbol `%s' undefined",
781 tokval->t_charptr);
782 return NULL;
783 } else if (critical == 1) {
784 error(ERR_NONFATAL,
785 "symbol `%s' not defined before use",
786 tokval->t_charptr);
787 return NULL;
788 } else {
789 if (opflags)
790 *opflags |= 1;
791 type = EXPR_UNKNOWN;
792 label_seg = NO_SEG;
793 label_ofs = 1;
794 }
795 }
796 if (opflags && is_extern(tokval->t_charptr))
797 *opflags |= OPFLAG_EXTERN;
798 }
799 addtotemp(type, label_ofs);
800 if (label_seg != NO_SEG)
801 addtotemp(EXPR_SEGBASE + label_seg, 1L);
802 break;
803 }
804 i = scan(scpriv, tokval);
805 return finishtemp();
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700806
807 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000808 error(ERR_NONFATAL, "expression syntax error");
809 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000810 }
811}
812
H. Peter Anvine2c80182005-01-15 22:15:51 +0000813void eval_global_info(struct ofmt *output, lfunc lookup_label,
814 loc_t * locp)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000815{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000816 outfmt = output;
817 labelfunc = lookup_label;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000818 location = locp;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000819}
820
H. Peter Anvine2c80182005-01-15 22:15:51 +0000821expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
822 int *fwref, int critical, efunc report_error,
823 struct eval_hints *hints)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000824{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000825 expr *e;
826 expr *f = NULL;
827
828 hint = hints;
829 if (hint)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000830 hint->type = EAH_NOHINT;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000831
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000832 if (critical & CRITICAL) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000833 critical &= ~CRITICAL;
834 bexpr = rexp0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000835 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000836 bexpr = expr0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000837
838 scan = sc;
839 scpriv = scprivate;
840 tokval = tv;
841 error = report_error;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000842 opflags = fwref;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000843
844 if (tokval->t_type == TOKEN_INVALID)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000845 i = scan(scpriv, tokval);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000846 else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000847 i = tokval->t_type;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000848
Keith Kaniosb7a89542007-04-12 02:40:54 +0000849 while (ntempexprs) /* initialize temporary storage */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000850 nasm_free(tempexprs[--ntempexprs]);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000851
H. Peter Anvine2c80182005-01-15 22:15:51 +0000852 e = bexpr(critical);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000853 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000854 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000855
856 if (i == TOKEN_WRT) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000857 i = scan(scpriv, tokval); /* eat the WRT */
858 f = expr6(critical);
859 if (!f)
860 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000861 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000862 e = scalar_mult(e, 1L, FALSE); /* strip far-absolute segment part */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000863 if (f) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000864 expr *g;
865 if (is_just_unknown(f))
866 g = unknown_expr();
867 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000868 int64_t value;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000869 begintemp();
870 if (!is_reloc(f)) {
871 error(ERR_NONFATAL, "invalid right-hand operand to WRT");
872 return NULL;
873 }
874 value = reloc_seg(f);
875 if (value == NO_SEG)
876 value = reloc_value(f) | SEG_ABS;
877 else if (!(value & SEG_ABS) && !(value % 2) && critical) {
878 error(ERR_NONFATAL, "invalid right-hand operand to WRT");
879 return NULL;
880 }
881 addtotemp(EXPR_WRT, value);
882 g = finishtemp();
883 }
884 e = add_vectors(e, g);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000885 }
886 return e;
887}