1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * parser.c source line parser for the Netwide Assembler
56 extern int in_abs_seg
; /* ABSOLUTE segment flag */
57 extern int32_t abs_seg
; /* ABSOLUTE segment */
58 extern int32_t abs_offset
; /* ABSOLUTE segment offset */
60 static int is_comma_next(void);
63 static struct tokenval tokval
;
64 static struct location
*location
; /* Pointer to current line's segment,offset */
66 void parser_global_info(struct location
* locp
)
71 static int prefix_slot(int prefix
)
102 nasm_error(ERR_PANIC
, "Invalid value %d passed to prefix_slot()", prefix
);
107 static void process_size_override(insn
*result
, int operand
)
109 if (tasm_compatible_mode
) {
110 switch ((int)tokval
.t_integer
) {
111 /* For TASM compatibility a size override inside the
112 * brackets changes the size of the operand, not the
113 * address type of the operand as it does in standard
114 * NASM syntax. Hence:
116 * mov eax,[DWORD val]
118 * is valid syntax in TASM compatibility mode. Note that
119 * you lose the ability to override the default address
120 * type for the instruction, but we never use anything
121 * but 32-bit flat model addressing in our code.
124 result
->oprs
[operand
].type
|= BITS8
;
127 result
->oprs
[operand
].type
|= BITS16
;
131 result
->oprs
[operand
].type
|= BITS32
;
134 result
->oprs
[operand
].type
|= BITS64
;
137 result
->oprs
[operand
].type
|= BITS80
;
140 result
->oprs
[operand
].type
|= BITS128
;
143 nasm_error(ERR_NONFATAL
,
144 "invalid operand size specification");
148 /* Standard NASM compatible syntax */
149 switch ((int)tokval
.t_integer
) {
151 result
->oprs
[operand
].eaflags
|= EAF_TIMESTWO
;
154 result
->oprs
[operand
].eaflags
|= EAF_REL
;
157 result
->oprs
[operand
].eaflags
|= EAF_ABS
;
160 result
->oprs
[operand
].disp_size
= 8;
161 result
->oprs
[operand
].eaflags
|= EAF_BYTEOFFS
;
166 if (result
->prefixes
[PPS_ASIZE
] &&
167 result
->prefixes
[PPS_ASIZE
] != tokval
.t_integer
)
168 nasm_error(ERR_NONFATAL
,
169 "conflicting address size specifications");
171 result
->prefixes
[PPS_ASIZE
] = tokval
.t_integer
;
174 result
->oprs
[operand
].disp_size
= 16;
175 result
->oprs
[operand
].eaflags
|= EAF_WORDOFFS
;
179 result
->oprs
[operand
].disp_size
= 32;
180 result
->oprs
[operand
].eaflags
|= EAF_WORDOFFS
;
183 result
->oprs
[operand
].disp_size
= 64;
184 result
->oprs
[operand
].eaflags
|= EAF_WORDOFFS
;
187 nasm_error(ERR_NONFATAL
, "invalid size specification in"
188 " effective address");
194 insn
*parse_line(int pass
, char *buffer
, insn
*result
, ldfunc ldef
)
196 bool insn_is_label
= false;
197 struct eval_hints hints
;
206 result
->forw_ref
= false;
210 i
= stdscan(NULL
, &tokval
);
212 result
->label
= NULL
; /* Assume no label */
213 result
->eops
= NULL
; /* must do this, whatever happens */
214 result
->operands
= 0; /* must initialize this */
216 /* Ignore blank lines */
217 if (i
== TOKEN_EOS
) {
218 result
->opcode
= I_none
;
225 (i
!= TOKEN_REG
|| !IS_SREG(tokval
.t_integer
))) {
226 nasm_error(ERR_NONFATAL
,
227 "label or instruction expected at start of line");
228 result
->opcode
= I_none
;
232 if (i
== TOKEN_ID
|| (insn_is_label
&& i
== TOKEN_INSN
)) {
233 /* there's a label here */
235 result
->label
= tokval
.t_charptr
;
236 i
= stdscan(NULL
, &tokval
);
237 if (i
== ':') { /* skip over the optional colon */
238 i
= stdscan(NULL
, &tokval
);
240 nasm_error(ERR_WARNING
| ERR_WARN_OL
| ERR_PASS1
,
241 "label alone on a line without a colon might be in error");
243 if (i
!= TOKEN_INSN
|| tokval
.t_integer
!= I_EQU
) {
245 * FIXME: location->segment could be NO_SEG, in which case
246 * it is possible we should be passing 'abs_seg'. Look into this.
247 * Work out whether that is *really* what we should be doing.
248 * Generally fix things. I think this is right as it is, but
249 * am still not certain.
251 ldef(result
->label
, in_abs_seg
? abs_seg
: location
->segment
,
252 location
->offset
, NULL
, true, false);
256 /* Just a label here */
257 if (i
== TOKEN_EOS
) {
258 result
->opcode
= I_none
;
262 for (j
= 0; j
< MAXPREFIX
; j
++)
263 result
->prefixes
[j
] = P_none
;
266 while (i
== TOKEN_PREFIX
||
267 (i
== TOKEN_REG
&& IS_SREG(tokval
.t_integer
))) {
271 * Handle special case: the TIMES prefix.
273 if (i
== TOKEN_PREFIX
&& tokval
.t_integer
== P_TIMES
) {
276 i
= stdscan(NULL
, &tokval
);
277 value
= evaluate(stdscan
, NULL
, &tokval
, NULL
, pass0
, nasm_error
, NULL
);
279 if (!value
) { /* but, error in evaluator */
280 result
->opcode
= I_none
; /* unrecoverable parse error: */
281 return result
; /* ignore this instruction */
283 if (!is_simple(value
)) {
284 nasm_error(ERR_NONFATAL
,
285 "non-constant argument supplied to TIMES");
288 result
->times
= value
->value
;
289 if (value
->value
< 0 && pass0
== 2) {
290 nasm_error(ERR_NONFATAL
, "TIMES value %"PRId64
" is negative",
296 int slot
= prefix_slot(tokval
.t_integer
);
297 if (result
->prefixes
[slot
]) {
298 if (result
->prefixes
[slot
] == tokval
.t_integer
)
299 nasm_error(ERR_WARNING
| ERR_PASS1
,
300 "instruction has redundant prefixes");
302 nasm_error(ERR_NONFATAL
,
303 "instruction has conflicting prefixes");
305 result
->prefixes
[slot
] = tokval
.t_integer
;
306 i
= stdscan(NULL
, &tokval
);
310 if (i
!= TOKEN_INSN
) {
314 for (j
= 0; j
< MAXPREFIX
; j
++) {
315 if ((pfx
= result
->prefixes
[j
]) != P_none
)
319 if (i
== 0 && pfx
!= P_none
) {
321 * Instruction prefixes are present, but no actual
322 * instruction. This is allowed: at this point we
323 * invent a notional instruction of RESB 0.
325 result
->opcode
= I_RESB
;
326 result
->operands
= 1;
327 result
->oprs
[0].type
= IMMEDIATE
;
328 result
->oprs
[0].offset
= 0L;
329 result
->oprs
[0].segment
= result
->oprs
[0].wrt
= NO_SEG
;
332 nasm_error(ERR_NONFATAL
, "parser: instruction expected");
333 result
->opcode
= I_none
;
338 result
->opcode
= tokval
.t_integer
;
339 result
->condition
= tokval
.t_inttwo
;
342 * INCBIN cannot be satisfied with incorrectly
343 * evaluated operands, since the correct values _must_ be known
344 * on the first pass. Hence, even in pass one, we set the
345 * `critical' flag on calling evaluate(), so that it will bomb
346 * out on undefined symbols.
348 if (result
->opcode
== I_INCBIN
) {
349 critical
= (pass0
< 2 ? 1 : 2);
352 critical
= (pass
== 2 ? 2 : 0);
354 if (result
->opcode
== I_DB
|| result
->opcode
== I_DW
||
355 result
->opcode
== I_DD
|| result
->opcode
== I_DQ
||
356 result
->opcode
== I_DT
|| result
->opcode
== I_DO
||
357 result
->opcode
== I_DY
|| result
->opcode
== I_INCBIN
) {
358 extop
*eop
, **tail
= &result
->eops
, **fixptr
;
362 result
->eops_float
= false;
365 * Begin to read the DB/DW/DD/DQ/DT/DO/INCBIN operands.
368 i
= stdscan(NULL
, &tokval
);
371 else if (first
&& i
== ':') {
372 insn_is_label
= true;
377 eop
= *tail
= nasm_malloc(sizeof(extop
));
380 eop
->type
= EOT_NOTHING
;
385 * is_comma_next() here is to distinguish this from
386 * a string used as part of an expression...
388 if (i
== TOKEN_STR
&& is_comma_next()) {
389 eop
->type
= EOT_DB_STRING
;
390 eop
->stringval
= tokval
.t_charptr
;
391 eop
->stringlen
= tokval
.t_inttwo
;
392 i
= stdscan(NULL
, &tokval
); /* eat the comma */
393 } else if (i
== TOKEN_STRFUNC
) {
395 const char *funcname
= tokval
.t_charptr
;
396 enum strfunc func
= tokval
.t_integer
;
397 i
= stdscan(NULL
, &tokval
);
400 i
= stdscan(NULL
, &tokval
);
402 if (i
!= TOKEN_STR
) {
403 nasm_error(ERR_NONFATAL
,
404 "%s must be followed by a string constant",
406 eop
->type
= EOT_NOTHING
;
408 eop
->type
= EOT_DB_STRING_FREE
;
410 string_transform(tokval
.t_charptr
, tokval
.t_inttwo
,
411 &eop
->stringval
, func
);
412 if (eop
->stringlen
== (size_t)-1) {
413 nasm_error(ERR_NONFATAL
, "invalid string for transform");
414 eop
->type
= EOT_NOTHING
;
417 if (parens
&& i
&& i
!= ')') {
418 i
= stdscan(NULL
, &tokval
);
420 nasm_error(ERR_NONFATAL
, "unterminated %s function",
425 i
= stdscan(NULL
, &tokval
);
426 } else if (i
== '-' || i
== '+') {
427 char *save
= stdscan_get();
429 sign
= (i
== '-') ? -1 : 1;
430 i
= stdscan(NULL
, &tokval
);
431 if (i
!= TOKEN_FLOAT
) {
433 i
= tokval
.t_type
= token
;
438 } else if (i
== TOKEN_FLOAT
) {
440 eop
->type
= EOT_DB_STRING
;
441 result
->eops_float
= true;
443 eop
->stringlen
= idata_bytes(result
->opcode
);
444 if (eop
->stringlen
> 16) {
445 nasm_error(ERR_NONFATAL
, "floating-point constant"
446 " encountered in DY instruction");
448 } else if (eop
->stringlen
< 1) {
449 nasm_error(ERR_NONFATAL
, "floating-point constant"
450 " encountered in unknown instruction");
452 * fix suggested by Pedro Gimeno... original line was:
453 * eop->type = EOT_NOTHING;
458 eop
= nasm_realloc(eop
, sizeof(extop
) + eop
->stringlen
);
461 eop
->stringval
= (char *)eop
+ sizeof(extop
);
462 if (!eop
->stringlen
||
463 !float_const(tokval
.t_charptr
, sign
,
464 (uint8_t *)eop
->stringval
,
465 eop
->stringlen
, nasm_error
))
466 eop
->type
= EOT_NOTHING
;
467 i
= stdscan(NULL
, &tokval
); /* eat the comma */
469 /* anything else, assume it is an expression */
473 value
= evaluate(stdscan
, NULL
, &tokval
, NULL
,
474 critical
, nasm_error
, NULL
);
476 if (!value
) { /* error in evaluator */
477 result
->opcode
= I_none
; /* unrecoverable parse error: */
478 return result
; /* ignore this instruction */
480 if (is_unknown(value
)) {
481 eop
->type
= EOT_DB_NUMBER
;
482 eop
->offset
= 0; /* doesn't matter what we put */
483 eop
->segment
= eop
->wrt
= NO_SEG
; /* likewise */
484 } else if (is_reloc(value
)) {
485 eop
->type
= EOT_DB_NUMBER
;
486 eop
->offset
= reloc_value(value
);
487 eop
->segment
= reloc_seg(value
);
488 eop
->wrt
= reloc_wrt(value
);
490 nasm_error(ERR_NONFATAL
,
491 "operand %d: expression is not simple"
492 " or relocatable", oper_num
);
497 * We're about to call stdscan(), which will eat the
498 * comma that we're currently sitting on between
499 * arguments. However, we'd better check first that it
502 if (i
== TOKEN_EOS
) /* also could be EOL */
505 nasm_error(ERR_NONFATAL
, "comma expected after operand %d",
507 result
->opcode
= I_none
;/* unrecoverable parse error: */
508 return result
; /* ignore this instruction */
512 if (result
->opcode
== I_INCBIN
) {
514 * Correct syntax for INCBIN is that there should be
515 * one string operand, followed by one or two numeric
518 if (!result
->eops
|| result
->eops
->type
!= EOT_DB_STRING
)
519 nasm_error(ERR_NONFATAL
, "`incbin' expects a file name");
520 else if (result
->eops
->next
&&
521 result
->eops
->next
->type
!= EOT_DB_NUMBER
)
522 nasm_error(ERR_NONFATAL
, "`incbin': second parameter is"
524 else if (result
->eops
->next
&& result
->eops
->next
->next
&&
525 result
->eops
->next
->next
->type
!= EOT_DB_NUMBER
)
526 nasm_error(ERR_NONFATAL
, "`incbin': third parameter is"
528 else if (result
->eops
->next
&& result
->eops
->next
->next
&&
529 result
->eops
->next
->next
->next
)
530 nasm_error(ERR_NONFATAL
,
531 "`incbin': more than three parameters");
535 * If we reach here, one of the above errors happened.
536 * Throw the instruction away.
538 result
->opcode
= I_none
;
540 } else /* DB ... */ if (oper_num
== 0)
541 nasm_error(ERR_WARNING
| ERR_PASS1
,
542 "no operand for data declaration");
544 result
->operands
= oper_num
;
550 * Now we begin to parse the operands. There may be up to four
551 * of these, separated by commas, and terminated by a zero token.
554 for (operand
= 0; operand
< MAX_OPERANDS
; operand
++) {
555 expr
*value
; /* used most of the time */
556 int mref
; /* is this going to be a memory ref? */
557 int bracket
; /* is it a [] mref, or a & mref? */
560 result
->oprs
[operand
].disp_size
= 0; /* have to zero this whatever */
561 result
->oprs
[operand
].eaflags
= 0; /* and this */
562 result
->oprs
[operand
].opflags
= 0;
564 i
= stdscan(NULL
, &tokval
);
566 break; /* end of operands: get out of here */
567 else if (first
&& i
== ':') {
568 insn_is_label
= true;
572 result
->oprs
[operand
].type
= 0; /* so far, no override */
573 while (i
== TOKEN_SPECIAL
) { /* size specifiers */
574 switch ((int)tokval
.t_integer
) {
576 if (!setsize
) /* we want to use only the first */
577 result
->oprs
[operand
].type
|= BITS8
;
582 result
->oprs
[operand
].type
|= BITS16
;
588 result
->oprs
[operand
].type
|= BITS32
;
593 result
->oprs
[operand
].type
|= BITS64
;
598 result
->oprs
[operand
].type
|= BITS80
;
603 result
->oprs
[operand
].type
|= BITS128
;
608 result
->oprs
[operand
].type
|= BITS256
;
612 result
->oprs
[operand
].type
|= TO
;
615 result
->oprs
[operand
].type
|= STRICT
;
618 result
->oprs
[operand
].type
|= FAR
;
621 result
->oprs
[operand
].type
|= NEAR
;
624 result
->oprs
[operand
].type
|= SHORT
;
627 nasm_error(ERR_NONFATAL
, "invalid operand size specification");
629 i
= stdscan(NULL
, &tokval
);
632 if (i
== '[' || i
== '&') { /* memory reference */
634 bracket
= (i
== '[');
635 i
= stdscan(NULL
, &tokval
); /* then skip the colon */
636 while (i
== TOKEN_SPECIAL
|| i
== TOKEN_PREFIX
) {
637 process_size_override(result
, operand
);
638 i
= stdscan(NULL
, &tokval
);
640 } else { /* immediate operand, or register */
642 bracket
= false; /* placate optimisers */
645 if ((result
->oprs
[operand
].type
& FAR
) && !mref
&&
646 result
->opcode
!= I_JMP
&& result
->opcode
!= I_CALL
) {
647 nasm_error(ERR_NONFATAL
, "invalid use of FAR operand specifier");
650 value
= evaluate(stdscan
, NULL
, &tokval
,
651 &result
->oprs
[operand
].opflags
,
652 critical
, nasm_error
, &hints
);
654 if (result
->oprs
[operand
].opflags
& OPFLAG_FORWARD
) {
655 result
->forw_ref
= true;
657 if (!value
) { /* nasm_error in evaluator */
658 result
->opcode
= I_none
; /* unrecoverable parse error: */
659 return result
; /* ignore this instruction */
661 if (i
== ':' && mref
) { /* it was seg:offset */
663 * Process the segment override.
665 if (value
[1].type
!= 0 ||
667 !IS_SREG(value
->type
))
668 nasm_error(ERR_NONFATAL
, "invalid segment override");
669 else if (result
->prefixes
[PPS_SEG
])
670 nasm_error(ERR_NONFATAL
,
671 "instruction has conflicting segment overrides");
673 result
->prefixes
[PPS_SEG
] = value
->type
;
674 if (IS_FSGS(value
->type
))
675 result
->oprs
[operand
].eaflags
|= EAF_FSGS
;
678 i
= stdscan(NULL
, &tokval
); /* then skip the colon */
679 while (i
== TOKEN_SPECIAL
|| i
== TOKEN_PREFIX
) {
680 process_size_override(result
, operand
);
681 i
= stdscan(NULL
, &tokval
);
683 value
= evaluate(stdscan
, NULL
, &tokval
,
684 &result
->oprs
[operand
].opflags
,
685 critical
, nasm_error
, &hints
);
687 if (result
->oprs
[operand
].opflags
& OPFLAG_FORWARD
) {
688 result
->forw_ref
= true;
690 /* and get the offset */
691 if (!value
) { /* but, error in evaluator */
692 result
->opcode
= I_none
; /* unrecoverable parse error: */
693 return result
; /* ignore this instruction */
698 if (mref
&& bracket
) { /* find ] at the end */
700 nasm_error(ERR_NONFATAL
, "parser: expecting ]");
702 } else { /* we got the required ] */
703 i
= stdscan(NULL
, &tokval
);
704 if (i
!= 0 && i
!= ',') {
705 nasm_error(ERR_NONFATAL
, "comma or end of line expected");
709 } else { /* immediate operand */
710 if (i
!= 0 && i
!= ',' && i
!= ':') {
711 nasm_error(ERR_NONFATAL
, "comma, colon or end of line expected");
713 } else if (i
== ':') {
714 result
->oprs
[operand
].type
|= COLON
;
718 do { /* error recovery */
719 i
= stdscan(NULL
, &tokval
);
720 } while (i
!= 0 && i
!= ',');
724 * now convert the exprs returned from evaluate()
725 * into operand descriptions...
728 if (mref
) { /* it's a memory reference */
730 int b
, i
, s
; /* basereg, indexreg, scale */
731 int64_t o
; /* offset */
733 b
= i
= -1, o
= s
= 0;
734 result
->oprs
[operand
].hintbase
= hints
.base
;
735 result
->oprs
[operand
].hinttype
= hints
.type
;
737 if (e
->type
&& e
->type
<= EXPR_REG_END
) { /* this bit's a register */
738 if (e
->value
== 1) /* in fact it can be basereg */
740 else /* no, it has to be indexreg */
741 i
= e
->type
, s
= e
->value
;
744 if (e
->type
&& e
->type
<= EXPR_REG_END
) { /* it's a 2nd register */
745 if (b
!= -1) /* If the first was the base, ... */
746 i
= e
->type
, s
= e
->value
; /* second has to be indexreg */
748 else if (e
->value
!= 1) { /* If both want to be index */
749 nasm_error(ERR_NONFATAL
,
750 "beroset-p-592-invalid effective address");
751 result
->opcode
= I_none
;
757 if (e
->type
!= 0) { /* is there an offset? */
758 if (e
->type
<= EXPR_REG_END
) { /* in fact, is there an error? */
759 nasm_error(ERR_NONFATAL
,
760 "beroset-p-603-invalid effective address");
761 result
->opcode
= I_none
;
764 if (e
->type
== EXPR_UNKNOWN
) {
765 result
->oprs
[operand
].opflags
|= OPFLAG_UNKNOWN
;
766 o
= 0; /* doesn't matter what */
767 result
->oprs
[operand
].wrt
= NO_SEG
; /* nor this */
768 result
->oprs
[operand
].segment
= NO_SEG
; /* or this */
770 e
++; /* go to the end of the line */
772 if (e
->type
== EXPR_SIMPLE
) {
776 if (e
->type
== EXPR_WRT
) {
777 result
->oprs
[operand
].wrt
= e
->value
;
780 result
->oprs
[operand
].wrt
= NO_SEG
;
782 * Look for a segment base type.
784 if (e
->type
&& e
->type
< EXPR_SEGBASE
) {
785 nasm_error(ERR_NONFATAL
,
786 "beroset-p-630-invalid effective address");
787 result
->opcode
= I_none
;
790 while (e
->type
&& e
->value
== 0)
792 if (e
->type
&& e
->value
!= 1) {
793 nasm_error(ERR_NONFATAL
,
794 "beroset-p-637-invalid effective address");
795 result
->opcode
= I_none
;
799 result
->oprs
[operand
].segment
=
800 e
->type
- EXPR_SEGBASE
;
803 result
->oprs
[operand
].segment
= NO_SEG
;
804 while (e
->type
&& e
->value
== 0)
807 nasm_error(ERR_NONFATAL
,
808 "beroset-p-650-invalid effective address");
809 result
->opcode
= I_none
;
816 result
->oprs
[operand
].wrt
= NO_SEG
;
817 result
->oprs
[operand
].segment
= NO_SEG
;
820 if (e
->type
!= 0) { /* there'd better be nothing left! */
821 nasm_error(ERR_NONFATAL
,
822 "beroset-p-663-invalid effective address");
823 result
->opcode
= I_none
;
827 /* It is memory, but it can match any r/m operand */
828 result
->oprs
[operand
].type
|= MEMORY_ANY
;
830 if (b
== -1 && (i
== -1 || s
== 0)) {
831 int is_rel
= globalbits
== 64 &&
832 !(result
->oprs
[operand
].eaflags
& EAF_ABS
) &&
834 !(result
->oprs
[operand
].eaflags
& EAF_FSGS
)) ||
835 (result
->oprs
[operand
].eaflags
& EAF_REL
));
837 result
->oprs
[operand
].type
|= is_rel
? IP_REL
: MEM_OFFS
;
839 result
->oprs
[operand
].basereg
= b
;
840 result
->oprs
[operand
].indexreg
= i
;
841 result
->oprs
[operand
].scale
= s
;
842 result
->oprs
[operand
].offset
= o
;
843 } else { /* it's not a memory reference */
844 if (is_just_unknown(value
)) { /* it's immediate but unknown */
845 result
->oprs
[operand
].type
|= IMMEDIATE
;
846 result
->oprs
[operand
].opflags
|= OPFLAG_UNKNOWN
;
847 result
->oprs
[operand
].offset
= 0; /* don't care */
848 result
->oprs
[operand
].segment
= NO_SEG
; /* don't care again */
849 result
->oprs
[operand
].wrt
= NO_SEG
; /* still don't care */
851 if(optimizing
>= 0 && !(result
->oprs
[operand
].type
& STRICT
)) {
853 result
->oprs
[operand
].type
|=
854 SBYTE16
| SBYTE32
| SBYTE64
| UDWORD64
| SDWORD64
;
856 } else if (is_reloc(value
)) { /* it's immediate */
857 result
->oprs
[operand
].type
|= IMMEDIATE
;
858 result
->oprs
[operand
].offset
= reloc_value(value
);
859 result
->oprs
[operand
].segment
= reloc_seg(value
);
860 result
->oprs
[operand
].wrt
= reloc_wrt(value
);
862 if (is_simple(value
)) {
863 if (reloc_value(value
) == 1)
864 result
->oprs
[operand
].type
|= UNITY
;
865 if (optimizing
>= 0 &&
866 !(result
->oprs
[operand
].type
& STRICT
)) {
867 int64_t v64
= reloc_value(value
);
868 int32_t v32
= (int32_t)v64
;
869 int16_t v16
= (int16_t)v32
;
871 if (v64
>= -128 && v64
<= 127)
872 result
->oprs
[operand
].type
|= SBYTE64
;
873 if (v32
>= -128 && v32
<= 127)
874 result
->oprs
[operand
].type
|= SBYTE32
;
875 if (v16
>= -128 && v16
<= 127)
876 result
->oprs
[operand
].type
|= SBYTE16
;
877 if ((uint64_t)v64
<= UINT64_C(0xffffffff))
878 result
->oprs
[operand
].type
|= UDWORD64
;
879 if (v64
>= -INT64_C(0x80000000) &&
880 v64
<= INT64_C(0x7fffffff))
881 result
->oprs
[operand
].type
|= SDWORD64
;
884 } else { /* it's a register */
887 if (value
->type
>= EXPR_SIMPLE
|| value
->value
!= 1) {
888 nasm_error(ERR_NONFATAL
, "invalid operand type");
889 result
->opcode
= I_none
;
894 * check that its only 1 register, not an expression...
896 for (i
= 1; value
[i
].type
; i
++)
897 if (value
[i
].value
) {
898 nasm_error(ERR_NONFATAL
, "invalid operand type");
899 result
->opcode
= I_none
;
903 /* clear overrides, except TO which applies to FPU regs */
904 if (result
->oprs
[operand
].type
& ~TO
) {
906 * we want to produce a warning iff the specified size
907 * is different from the register size
909 rs
= result
->oprs
[operand
].type
& SIZE_MASK
;
913 result
->oprs
[operand
].type
&= TO
;
914 result
->oprs
[operand
].type
|= REGISTER
;
915 result
->oprs
[operand
].type
|= nasm_reg_flags
[value
->type
];
916 result
->oprs
[operand
].basereg
= value
->type
;
918 if (rs
&& (result
->oprs
[operand
].type
& SIZE_MASK
) != rs
)
919 nasm_error(ERR_WARNING
| ERR_PASS1
,
920 "register size specification ignored");
925 result
->operands
= operand
; /* set operand count */
927 /* clear remaining operands */
928 while (operand
< MAX_OPERANDS
)
929 result
->oprs
[operand
++].type
= 0;
932 * Transform RESW, RESD, RESQ, REST, RESO, RESY into RESB.
934 switch (result
->opcode
) {
936 result
->opcode
= I_RESB
;
937 result
->oprs
[0].offset
*= 2;
940 result
->opcode
= I_RESB
;
941 result
->oprs
[0].offset
*= 4;
944 result
->opcode
= I_RESB
;
945 result
->oprs
[0].offset
*= 8;
948 result
->opcode
= I_RESB
;
949 result
->oprs
[0].offset
*= 10;
952 result
->opcode
= I_RESB
;
953 result
->oprs
[0].offset
*= 16;
956 result
->opcode
= I_RESB
;
957 result
->oprs
[0].offset
*= 32;
966 static int is_comma_next(void)
973 i
= stdscan(NULL
, &tv
);
976 return (i
== ',' || i
== ';' || !i
);
979 void cleanup_insn(insn
* i
)
983 while ((e
= i
->eops
)) {
985 if (e
->type
== EOT_DB_STRING_FREE
)
986 nasm_free(e
->stringval
);