1 /****************************************************************************
2 *
3 * Open Watcom Project
4 *
5 * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
6 *
7 * ========================================================================
8 *
9 * This file contains Original Code and/or Modifications of Original
10 * Code as defined in and that are subject to the Sybase Open Watcom
11 * Public License version 1.0 (the 'License'). You may not use this file
12 * except in compliance with the License. BY USING THIS FILE YOU AGREE TO
13 * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
14 * provided with the Original Code and Modifications, and is also
15 * available at www.sybase.com/developer/opensource.
16 *
17 * The Original Code and all software distributed under the License are
18 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
19 * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
20 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
22 * NON-INFRINGEMENT. Please see the License for the specific language
23 * governing rights and limitations under the License.
24 *
25 * ========================================================================
26 *
27 * Description: Parser
28 *
29 ****************************************************************************/
30
31 #include <ctype.h>
32 #include <limits.h>
33
34 #include "globals.h"
35 #include "memalloc.h"
36 #include "parser.h"
37 #include "preproc.h"
38 #include "reswords.h"
39 #include "codegen.h"
40 #include "expreval.h"
41 #include "fixup.h"
42 #include "types.h"
43 #include "label.h"
44 #include "segment.h"
45 #include "assume.h"
46 #include "proc.h"
47 #include "myassert.h"
48 #include "input.h"
49 #include "tokenize.h"
50 #include "listing.h"
51 #include "data.h"
52 #include "fastpass.h"
53 #include "omf.h"
54 #include "omfspec.h"
55 #include "condasm.h"
56 #include "extern.h"
57 #include "atofloat.h"
58
59 #define ADDRSIZE( s, x ) ( ( ( x ) ^ ( s ) ) ? TRUE : FALSE )
60 #define IS_ADDR32( s ) ( s->Ofssize ? ( s->prefix.adrsiz == FALSE ) : ( s->prefix.adrsiz == TRUE ))
61
62 #define OPSIZE32( s ) ( ( s->Ofssize ) ? FALSE : TRUE )
63 #define OPSIZE16( s ) ( ( s->Ofssize ) ? TRUE : FALSE )
64
65 #define InWordRange( val ) ( (val > 65535 || val < -65535) ? FALSE : TRUE )
66
67 extern ret_code (* const directive_tab[])( int, struct asm_tok[] );
68
69 /* parsing of branch instructions with imm operand is found in branch.c */
70 extern ret_code process_branch( struct code_info *, unsigned, const struct expr * );
71
72 extern enum proc_status ProcStatus;
73 //extern struct asym symPC; /* '$' symbol */
74 extern const int_64 maxintvalues[];
75 extern const int_64 minintvalues[];
76 extern const struct opnd_class opnd_clstab[];
77 #if AVXSUPP
78 extern const uint_8 vex_flags[];
79 #endif
80 extern int_8 Frame_Type; /* Frame of current fixup */
81 extern uint_16 Frame_Datum; /* Frame datum of current fixup */
82
83 struct asym *SegOverride; /* set by SetSegOverride() */
84 static enum assume_segreg LastRegOverride;/* needed for CMPS */
85
86 /* linked lists of: index
87 *--------------------------------
88 * - undefined symbols TAB_UNDEF
89 * - externals TAB_EXT
90 * - segments TAB_SEG
91 * - groups TAB_GRP
92 * - procedures TAB_PROC
93 * - aliases TAB_ALIAS
94 */
95 struct symbol_queue SymTables[TAB_LAST];
96
97 /* add item to linked list of symbols */
98
sym_add_table(struct symbol_queue * queue,struct dsym * item)99 void sym_add_table( struct symbol_queue *queue, struct dsym *item )
100 /*****************************************************************/
101 {
102 #ifdef DEBUG_OUT
103 if ( queue == &SymTables[TAB_UNDEF] )
104 item->sym.fwdref = TRUE;
105 #endif
106 if( queue->head == NULL ) {
107 queue->head = queue->tail = item;
108 item->next = item->prev = NULL;
109 } else {
110 item->prev = queue->tail;
111 queue->tail->next = item;
112 queue->tail = item;
113 item->next = NULL;
114 }
115 }
116
117 /* remove an item from a symbol queue.
118 * this is called only for TAB_UNDEF and TAB_EXT,
119 * segments, groups, procs or aliases never change their state.
120 */
sym_remove_table(struct symbol_queue * queue,struct dsym * item)121 void sym_remove_table( struct symbol_queue *queue, struct dsym *item )
122 /********************************************************************/
123 {
124 /* unlink the node */
125 if( item->prev )
126 item->prev->next = item->next;
127 if( item->next )
128 item->next->prev = item->prev;
129
130 //if ( dir->next == NULL )
131 // dir->next = dir->prev;
132
133 if ( queue->head == item )
134 queue->head = item->next;
135 if ( queue->tail == item )
136 queue->tail = item->prev;
137
138 item->next = NULL;
139 item->prev = NULL;
140 }
141
sym_ext2int(struct asym * sym)142 void sym_ext2int( struct asym *sym )
143 /**********************************/
144 /* Change symbol state from SYM_EXTERNAL to SYM_INTERNAL.
145 * called by:
146 * - CreateConstant() EXTERNDEF name:ABS -> constant
147 * - CreateAssemblyTimeVariable() EXTERNDEF name:ABS -> assembly-time variable
148 * - CreateLabel() EXTERNDEF name:NEAR|FAR|PROC -> code label
149 * - data_dir() EXTERNDEF name:typed memref -> data label
150 * - ProcDir() PROTO or EXTERNDEF name:NEAR|FAR|PROC -> PROC
151 */
152 {
153 /* v2.07: GlobalQueue has been removed */
154 if ( sym->isproc == FALSE && sym->ispublic == FALSE ) {
155 sym->ispublic = TRUE;
156 AddPublicData( sym );
157 }
158 sym_remove_table( &SymTables[TAB_EXT], (struct dsym *)sym );
159 if ( sym->isproc == FALSE ) /* v2.01: don't clear flags for PROTO */
160 sym->first_size = 0;
161 sym->state = SYM_INTERNAL;
162 }
163
GetLangType(int * i,struct asm_tok tokenarray[],enum lang_type * plang)164 ret_code GetLangType( int *i, struct asm_tok tokenarray[], enum lang_type *plang )
165 /********************************************************************************/
166 {
167 if( tokenarray[*i].token == T_RES_ID ) {
168 #if 1 /* v2.03: simplified */
169 if ( tokenarray[(*i)].tokval >= T_C &&
170 tokenarray[(*i)].tokval <= T_FASTCALL ) {
171 *plang = tokenarray[(*i)].bytval;
172 (*i)++;
173 return( NOT_ERROR );
174 }
175 #else
176 switch( tokenarray[(*i)].tokval ) {
177 case T_C: *plang = LANG_C; break;
178 case T_SYSCALL: *plang = LANG_SYSCALL; break;
179 case T_STDCALL: *plang = LANG_STDCALL; break;
180 case T_PASCAL: *plang = LANG_PASCAL; break;
181 case T_FORTRAN: *plang = LANG_FORTRAN; break;
182 case T_BASIC: *plang = LANG_BASIC; break;
183 case T_FASTCALL: *plang = LANG_FASTCALL; break;
184 default:
185 return( ERROR );
186 }
187 (*i)++;
188 return( NOT_ERROR );
189 #endif
190 }
191 return( ERROR );
192 }
193
194 /* get size of a register
195 * v2.06: rewritten, since the sflags field
196 * does now contain size for GPR, STx, MMX, XMM regs.
197 */
198
SizeFromRegister(int registertoken)199 int SizeFromRegister( int registertoken )
200 /***************************************/
201 {
202 unsigned flags;
203 flags = GetSflagsSp( registertoken ) & SFR_SIZMSK;
204
205 if ( flags )
206 return( flags );
207
208 flags = GetValueSp( registertoken );
209 if ( flags & OP_SR )
210 return( CurrWordSize );
211
212 /* CRx, DRx, TRx remaining */
213 #if AMD64_SUPPORT
214 return( ModuleInfo.Ofssize == USE64 ? 8 : 4 );
215 #else
216 return( 4 );
217 #endif
218 }
219
220 /* get size from memory type */
221
222 /* MT_PROC memtype is set ONLY in typedefs ( state=SYM_TYPE, typekind=TYPE_TYPEDEF)
223 * and makes the type a PROTOTYPE. Due to technical (obsolete?) restrictions the
224 * prototype data is stored in another symbol and is referenced in the typedef's
225 * target_type member.
226 */
227
SizeFromMemtype(enum memtype mem_type,int Ofssize,struct asym * type)228 int SizeFromMemtype( enum memtype mem_type, int Ofssize, struct asym *type )
229 /**************************************************************************/
230 {
231 if ( ( mem_type & MT_SPECIAL) == 0 )
232 return ( (mem_type & MT_SIZE_MASK) + 1 );
233
234 if ( Ofssize == USE_EMPTY )
235 Ofssize = ModuleInfo.Ofssize;
236
237 switch ( mem_type ) {
238 case MT_NEAR:
239 DebugMsg1(("SizeFromMemtype( MT_NEAR, Ofssize=%u )=%u\n", Ofssize, 2 << Ofssize ));
240 return ( 2 << Ofssize );
241 case MT_FAR:
242 DebugMsg1(("SizeFromMemtype( MT_FAR, Ofssize=%u )=%u\n", Ofssize, ( 2 << Ofssize ) + 2 ));
243 return ( ( 2 << Ofssize ) + 2 );
244 case MT_PROC:
245 DebugMsg1(("SizeFromMemtype( MT_PROC, Ofssize=%u, type=%s )=%u\n", Ofssize, type->name, ( 2 << Ofssize ) + ( type->isfar ? 2 : 0 ) ));
246 /* v2.09: use type->isfar setting */
247 //return( ( 2 << Ofssize ) + ( ( SIZE_CODEPTR & ( 1 << ModuleInfo.model ) ) ? 2 : 0 ) );
248 return( ( 2 << Ofssize ) + ( type->isfar ? 2 : 0 ) );
249 case MT_PTR:
250 DebugMsg1(("SizeFromMemtype( MT_PTR, Ofssize=%u )=%u\n", Ofssize, ( 2 << Ofssize ) + ( ( SIZE_DATAPTR & ( 1 << ModuleInfo.model ) ) ? 2 : 0 ) ));
251 return( ( 2 << Ofssize ) + ( ( SIZE_DATAPTR & ( 1 << ModuleInfo.model ) ) ? 2 : 0 ) );
252 case MT_TYPE:
253 if ( type )
254 return( type->total_size );
255 default:
256 DebugMsg1(("SizeFromMemtype( memtype=%Xh, Ofssize=%u )=%u\n", mem_type, Ofssize, 0 ));
257 return( 0 );
258 }
259 }
260
261 /* get memory type from size */
262
MemtypeFromSize(int size,enum memtype * ptype)263 ret_code MemtypeFromSize( int size, enum memtype *ptype )
264 /*******************************************************/
265 {
266 int i;
267 for ( i = T_BYTE; SpecialTable[i].type == RWT_STYPE; i++ ) {
268 if( ( SpecialTable[i].bytval & MT_SPECIAL ) == 0 ) {
269 /* the size is encoded 0-based in field mem_type */
270 if( ( ( SpecialTable[i].bytval & MT_SIZE_MASK) + 1 ) == size ) {
271 *ptype = SpecialTable[i].bytval;
272 return( NOT_ERROR );
273 }
274 }
275 }
276 return( ERROR );
277 }
278
OperandSize(enum operand_type opnd,const struct code_info * CodeInfo)279 int OperandSize( enum operand_type opnd, const struct code_info *CodeInfo )
280 /*************************************************************************/
281 {
282 /* v2.0: OP_M8_R8 and OP_M16_R16 have the DFT bit set! */
283 if( opnd == OP_NONE ) {
284 return( 0 );
285 } else if( opnd == OP_M ) {
286 return( SizeFromMemtype( CodeInfo->mem_type, CodeInfo->Ofssize, NULL ) );
287 } else if( opnd & ( OP_R8 | OP_M08 | OP_I8 ) ) {
288 return( 1 );
289 } else if( opnd & ( OP_R16 | OP_M16 | OP_I16 | OP_SR ) ) {
290 return( 2 );
291 } else if( opnd & ( OP_R32 | OP_M32 | OP_I32 ) ) {
292 return( 4 );
293 #if AMD64_SUPPORT
294 } else if( opnd & ( OP_R64 | OP_M64 | OP_MMX | OP_I64 ) ) {
295 #else
296 } else if( opnd & ( OP_M64 | OP_MMX ) ) {
297 #endif
298 return( 8 );
299 // } else if( opnd & ( OP_I | OP_I48 ) ) {
300 } else if( opnd & ( OP_I48 | OP_M48 ) ) {
301 return( 6 );
302 } else if( opnd & ( OP_STI | OP_M80 ) ) {
303 return( 10 );
304 } else if( opnd & ( OP_XMM | OP_M128 ) ) {
305 return( 16 );
306 #if AVXSUPP
307 } else if( opnd & ( OP_YMM | OP_M256 ) ) {
308 return( 32 );
309 #endif
310 } else if( opnd & OP_RSPEC ) {
311 #if AMD64_SUPPORT
312 return( ( CodeInfo->Ofssize == USE64 ) ? 8 : 4 );
313 #else
314 return( 4 );
315 #endif
316 }
317 DebugMsg1(("OperandSize: unhandled operand type %Xh!!!\n", opnd ));
318 return( 0 );
319 }
320
comp_mem16(int reg1,int reg2)321 static int comp_mem16( int reg1, int reg2 )
322 /*****************************************/
323 /*
324 - compare and return the r/m field encoding of 16-bit address mode;
325 - call by set_rm_sib() only;
326 */
327 {
328 switch( reg1 ) {
329 case T_BX:
330 switch( reg2 ) {
331 case T_SI: return( RM_BX_SI ); /* 00 */
332 case T_DI: return( RM_BX_DI ); /* 01 */
333 }
334 break;
335 case T_BP:
336 switch( reg2 ) {
337 case T_SI: return( RM_BP_SI ); /* 02 */
338 case T_DI: return( RM_BP_DI ); /* 03 */
339 }
340 break;
341 default:
342 return( EmitError( MULTIPLE_INDEX_REGISTERS_NOT_ALLOWED ) );
343 }
344 return( EmitError( MULTIPLE_BASE_REGISTERS_NOT_ALLOWED ) );
345 }
346
check_assume(struct code_info * CodeInfo,const struct asym * sym,enum assume_segreg default_reg)347 static void check_assume( struct code_info *CodeInfo, const struct asym *sym, enum assume_segreg default_reg )
348 /************************************************************************************************************/
349 /* Check if an assumed segment register is found, and
350 * set CodeInfo->RegOverride if necessary.
351 * called by seg_override().
352 * at least either sym or SegOverride is != NULL.
353 */
354 {
355 enum assume_segreg reg;
356 struct asym *assume;
357
358 if( sym && sym->state == SYM_UNDEFINED )
359 return;
360
361 reg = GetAssume( SegOverride, sym, default_reg, &assume );
362 /* set global vars Frame and Frame_Datum */
363 DebugMsg1(("check_assume(%s): calling SetFixupFrame(%s, FALSE)\n", sym ? sym->name : "NULL", assume ? assume->name : "NULL" ));
364 SetFixupFrame( assume, FALSE );
365
366 if( reg == ASSUME_NOTHING ) {
367 if ( sym ) {
368 //if( sym->state != SYM_EXTERNAL && sym->state != SYM_STACK ) {
369 /* v1.95: condition changed. Now there's an error msg only if
370 * the symbol has an explicite segment.
371 */
372 if( sym->segment != NULL ) {
373 DebugMsg1(("check_assume: no segment register available to access label %s\n", sym->name ));
374 EmitErr( CANNOT_ACCESS_LABEL_THROUGH_SEGMENT_REGISTERS, sym->name );
375 } else
376 CodeInfo->prefix.RegOverride = default_reg;
377 } else {
378 DebugMsg1(("check_assume: no segment register available to access seg-label %s\n", SegOverride->name ));
379 EmitErr( CANNOT_ACCESS_LABEL_THROUGH_SEGMENT_REGISTERS, SegOverride->name );
380 }
381 } else if( default_reg != EMPTY ) {
382 CodeInfo->prefix.RegOverride = reg;
383 }
384 }
385
seg_override(struct code_info * CodeInfo,int seg_reg,const struct asym * sym,bool direct)386 static void seg_override( struct code_info *CodeInfo, int seg_reg, const struct asym *sym, bool direct )
387 /******************************************************************************************************/
388 /*
389 * called by set_rm_sib(). determine if segment override is necessary
390 * with the current address mode;
391 * - seg_reg: register index (T_DS, T_BP, T_EBP, T_BX, ... )
392 */
393 {
394 enum assume_segreg default_seg;
395 struct asym *assume;
396
397 /* don't touch segment overrides for string instructions */
398 //if ( InstrTable[optable_idx[CodeInfo->token]].allowed_prefix == AP_REP ||
399 // InstrTable[optable_idx[CodeInfo->token]].allowed_prefix == AP_REPxx )
400 if ( CodeInfo->pinstr->allowed_prefix == AP_REP ||
401 CodeInfo->pinstr->allowed_prefix == AP_REPxx )
402 return;
403
404 if( CodeInfo->token == T_LEA ) {
405 CodeInfo->prefix.RegOverride = ASSUME_NOTHING; /* skip segment override */
406 SetFixupFrame( sym, FALSE );
407 return;
408 }
409
410 switch( seg_reg ) {
411 //case T_SS: /* doesn't happen */
412 case T_BP:
413 case T_EBP:
414 case T_ESP:
415 /* todo: check why cases T_RBP/T_RSP aren't needed! */
416 default_seg = ASSUME_SS;
417 break;
418 default:
419 default_seg = ASSUME_DS;
420 }
421
422 if( CodeInfo->prefix.RegOverride != EMPTY ) {
423 assume = GetOverrideAssume( CodeInfo->prefix.RegOverride );
424 /* assume now holds assumed SEG/GRP symbol */
425 if ( sym ) {
426 DebugMsg1(("seg_override: sym=%s, assume=%s, calling SetFixupFrame()\n",
427 sym->name, assume ? assume->name : "NULL" ));
428 SetFixupFrame( assume ? assume : sym, FALSE );
429 } else if ( direct ) {
430 /* no label attached (DS:[0]). No fixup is to be created! */
431 if ( assume ) {
432 DebugMsg1(("seg_override, direct addressing: prefix.adrsiz will be set, assume=%s[Ofssize=%u] CI->Ofssize=%u\n",
433 assume->name, GetSymOfssize( assume ), CodeInfo->Ofssize ));
434 /* v2.12: args for ADDRSIZE must be USE16 and "> USE16". The old way
435 * caused error 'magnitude of offset exceeds 16 bit' to be displayed if
436 * module contained USE32 & USE64 segments. Todo: Most likely to be adjusted
437 * in the other ADDRSIZE() locations as well!
438 */
439 //CodeInfo->prefix.adrsiz = ADDRSIZE( CodeInfo->Ofssize, GetSymOfssize( assume ) );
440 CodeInfo->prefix.adrsiz = ADDRSIZE( CodeInfo->Ofssize > USE16, GetSymOfssize( assume ) > USE16 );
441 DebugMsg1(("seg_override: new CI->prefix.adrsiz=%u\n", CodeInfo->prefix.adrsiz ));
442 } else {
443 /* v2.01: if -Zm, then use current CS offset size.
444 * This isn't how Masm v6 does it, but it matches Masm v5.
445 */
446 DebugMsg1(("seg_override, direct addressing: prefix.adrsiz will be set, no assume, CI->Ofssize=%u, MI.defOfssize=%u (MI.Ofssize=%u)\n",
447 CodeInfo->Ofssize, ModuleInfo.defOfssize, ModuleInfo.Ofssize ));
448 if ( ModuleInfo.m510 )
449 CodeInfo->prefix.adrsiz = ADDRSIZE( CodeInfo->Ofssize, ModuleInfo.Ofssize );
450 else {
451 /* v2.12: see comment above */
452 CodeInfo->prefix.adrsiz = ADDRSIZE( CodeInfo->Ofssize > USE16, ModuleInfo.defOfssize > USE16 );
453 //CodeInfo->prefix.adrsiz = ADDRSIZE( CodeInfo->Ofssize, ModuleInfo.defOfssize );
454 }
455 }
456 }
457 } else {
458 if ( sym || SegOverride )
459 check_assume( CodeInfo, sym, default_seg );
460 if ( sym == NULL && SegOverride ) {
461 CodeInfo->prefix.adrsiz = ADDRSIZE( CodeInfo->Ofssize, GetSymOfssize( SegOverride ) );
462 }
463 }
464
465 if( CodeInfo->prefix.RegOverride == default_seg ) {
466 CodeInfo->prefix.RegOverride = ASSUME_NOTHING; /* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
467 }
468 }
469
470 /* prepare fixup creation
471 * called by:
472 * - idata_fixup()
473 * - process_branch() in branch.c
474 * - data_item() in data.c
475 */
476
set_frame(const struct asym * sym)477 void set_frame( const struct asym *sym )
478 /**************************************/
479 {
480 SetFixupFrame( SegOverride ? SegOverride : sym, FALSE );
481 }
482
483 /* set fixup frame if OPTION OFFSET:SEGMENT is set and
484 * OFFSET or SEG operator was used.
485 * called by:
486 * - idata_fixup()
487 * - data_item()
488 */
set_frame2(const struct asym * sym)489 void set_frame2( const struct asym *sym )
490 /***************************************/
491 {
492 SetFixupFrame( SegOverride ? SegOverride : sym, TRUE );
493 }
494
set_rm_sib(struct code_info * CodeInfo,unsigned CurrOpnd,char ss,int index,int base,const struct asym * sym)495 static ret_code set_rm_sib( struct code_info *CodeInfo, unsigned CurrOpnd, char ss, int index, int base, const struct asym *sym )
496 /*******************************************************************************************************************************/
497 /*
498 * encode ModRM and SIB byte for memory addressing.
499 * called by memory_operand().
500 * in: ss = scale factor (00=1,40=2,80=4,C0=8)
501 * index = index register (T_DI, T_ESI, ...)
502 * base = base register (T_EBP, ... )
503 * sym = symbol (direct addressing, displacement)
504 * out: CodeInfo->rm_byte, CodeInfo->sib, CodeInfo->prefix.rex
505 */
506 {
507 int temp;
508 unsigned char mod_field;
509 unsigned char rm_field;
510 unsigned char base_reg;
511 unsigned char idx_reg;
512 #if AMD64_SUPPORT
513 unsigned char bit3_base;
514 unsigned char bit3_idx;
515 unsigned char rex;
516 #endif
517
518 DebugMsg1(("set_rm_sib(scale=%u, index=%d, base=%d, sym=%s) enter [CI.adrsiz=%u]\n", 1 << (ss >> 6), index, base, sym ? sym->name : "NULL", CodeInfo->prefix.adrsiz ));
519
520 /* clear mod */
521 rm_field = 0;
522 #if AMD64_SUPPORT
523 bit3_base = 0;
524 bit3_idx = 0;
525 rex = 0;
526 #endif
527 if( CodeInfo->opnd[CurrOpnd].InsFixup != NULL ) { /* symbolic displacement given? */
528 mod_field = MOD_10;
529 } else if( CodeInfo->opnd[CurrOpnd].data32l == 0 ) { /* no displacement (or 0) */
530 mod_field = MOD_00;
531 } else if( ( CodeInfo->opnd[CurrOpnd].data32l > SCHAR_MAX )
532 || ( CodeInfo->opnd[CurrOpnd].data32l < SCHAR_MIN ) ) {
533 mod_field = MOD_10; /* full size displacement */
534 } else {
535 mod_field = MOD_01; /* byte size displacement */
536 }
537
538 if( ( index == EMPTY ) && ( base == EMPTY ) ) {
539 /* direct memory.
540 * clear the rightmost 3 bits
541 */
542 CodeInfo->isdirect = TRUE;
543 mod_field = MOD_00;
544
545 /* default is DS:[], DS: segment override is not needed */
546 seg_override( CodeInfo, T_DS, sym, TRUE );
547
548 DebugMsg1(( "set_rm_sib: direct addressing, CI.Ofssize=%u / adrsize=%u / data=%" I32_SPEC "X\n",
549 CodeInfo->Ofssize, CodeInfo->prefix.adrsiz, CodeInfo->opnd[CurrOpnd].data32l ));
550 //if( !IS_ADDR32( CodeInfo ) ) {
551 if( ( CodeInfo->Ofssize == USE16 && CodeInfo->prefix.adrsiz == 0 ) ||
552 ( CodeInfo->Ofssize == USE32 && CodeInfo->prefix.adrsiz == 1 )) {
553 if( !InWordRange( CodeInfo->opnd[CurrOpnd].data32l ) ) {
554 /* expect 16-bit but got 32-bit address */
555 DebugMsg1(( "set_rm_sib: error, Ofssize=%u, adrsize=%u, data=%" I32_SPEC "X\n",
556 CodeInfo->Ofssize, CodeInfo->prefix.adrsiz, CodeInfo->opnd[CurrOpnd].data32l ));
557 return( EmitError( MAGNITUDE_OF_OFFSET_EXCEEDS_16BIT ) );
558 }
559 rm_field = RM_D16; /* D16=110b */
560 } else {
561 rm_field = RM_D32; /* D32=101b */
562 #if AMD64_SUPPORT
563 /* v2.03: the non-RIP encoding for 64bit uses a redundant SIB mode (base=none, index=none) */
564 /* v2.11: always use 64-bit non-RIP addressing if no fixup has been created. */
565 //if ( CodeInfo->Ofssize == USE64 && CodeInfo->prefix.RegOverride != EMPTY && SegOverride != &ModuleInfo.flat_grp->sym ) {
566 if ( CodeInfo->Ofssize == USE64 && CodeInfo->opnd[CurrOpnd].InsFixup == NULL ) {
567 DebugMsg1(( "set_rm_sib: 64-bit, no fixup, data64=%" I64_SPEC "X\n", CodeInfo->opnd[CurrOpnd].data64 ));
568 rm_field = RM_SIB;
569 CodeInfo->sib = 0x25; /* IIIBBB, base=101b, index=100b */
570 }
571 #endif
572 }
573 DebugMsg1(("set_rm_sib, direct, CodeInfo->prefix.adrsiz=%u\n", CodeInfo->prefix.adrsiz ));
574 } else if( ( index == EMPTY ) && ( base != EMPTY ) ) {
575 /* for SI, DI and BX: default is DS:[],
576 * DS: segment override is not needed
577 * for BP: default is SS:[], SS: segment override is not needed
578 */
579 switch( base ) {
580 case T_SI:
581 rm_field = RM_SI; /* 4 */
582 break;
583 case T_DI:
584 rm_field = RM_DI; /* 5 */
585 break;
586 case T_BP:
587 rm_field = RM_BP; /* 6 */
588 if( mod_field == MOD_00 ) {
589 mod_field = MOD_01;
590 }
591 break;
592 case T_BX:
593 rm_field = RM_BX; /* 7 */
594 break;
595 default: /* for 386 and up */
596 base_reg = GetRegNo( base );
597 #if AMD64_SUPPORT
598 bit3_base = base_reg >> 3;
599 base_reg &= BIT_012;
600 #endif
601 rm_field = base_reg;
602 DebugMsg1(("set_rm_sib: base_reg is %u\n", base_reg ));
603 if ( base_reg == 4 ) {
604 /* 4 is RSP/ESP or R12/R12D, which must use SIB encoding.
605 * SSIIIBBB, ss = 00, index = 100b ( no index ), base = 100b ( ESP ) */
606 CodeInfo->sib = 0x24;
607 } else if ( base_reg == 5 && mod_field == MOD_00 ) {
608 /* 5 is [E|R]BP or R13[D]. Needs displacement */
609 mod_field = MOD_01;
610 }
611 #if AMD64_SUPPORT
612 /* v2.02 */
613 //rex = ( bit3_base << 2 ); /* set REX_R */
614 rex = bit3_base; /* set REX_R */
615 #endif
616 }
617 #if AMD64_SUPPORT
618 DebugMsg1(("set_rm_sib, indirect with base, mod_field=%X, rm_field=%X, rex=%X\n", mod_field, rm_field, rex ));
619 #else
620 DebugMsg1(("set_rm_sib, indirect with base, rm_field=%X\n", rm_field ));
621 #endif
622 seg_override( CodeInfo, base, sym, FALSE );
623 } else if( ( index != EMPTY ) && ( base == EMPTY ) ) {
624 idx_reg = GetRegNo( index );
625 #if AMD64_SUPPORT
626 bit3_idx = idx_reg >> 3;
627 idx_reg &= BIT_012;
628 #endif
629 /* mod field is 00 */
630 mod_field = MOD_00;
631 /* s-i-b is present ( r/m = 100b ) */
632 rm_field = RM_SIB;
633 /* scale factor, index, base ( 0x05 => no base reg ) */
634 CodeInfo->sib = ( ss | ( idx_reg << 3 ) | 0x05 );
635 #if AMD64_SUPPORT
636 rex = (bit3_idx << 1); /* set REX_X */
637 #endif
638 /* default is DS:[], DS: segment override is not needed */
639 seg_override( CodeInfo, T_DS, sym, FALSE );
640 } else {
641 /* base != EMPTY && index != EMPTY */
642 base_reg = GetRegNo( base );
643 idx_reg = GetRegNo( index );
644 #if AMD64_SUPPORT
645 bit3_base = base_reg >> 3;
646 bit3_idx = idx_reg >> 3;
647 base_reg &= BIT_012;
648 idx_reg &= BIT_012;
649 #endif
650 if ( ( GetSflagsSp( base ) & GetSflagsSp( index ) & SFR_SIZMSK ) == 0 ) {
651 return( EmitError( CANNOT_MIX_16_AND_32_BIT_REGISTERS ) );
652 }
653 switch( index ) {
654 case T_BX:
655 case T_BP:
656 if( ( temp = comp_mem16( index, base ) ) == ERROR )
657 return( ERROR );
658 rm_field = temp;
659 seg_override( CodeInfo, index, sym, FALSE );
660 break;
661 case T_SI:
662 case T_DI:
663 if( ( temp = comp_mem16( base, index ) ) == ERROR )
664 return( ERROR );
665 rm_field = temp;
666 seg_override( CodeInfo, base, sym, FALSE );
667 break;
668 #if AMD64_SUPPORT
669 case T_RSP:
670 #endif
671 case T_ESP:
672 //EmitErr( CANNOT_BE_USED_AS_INDEX_REGISTER, ??? );
673 return( EmitError( INVALID_USE_OF_REGISTER ) );
674 default:
675 if( base_reg == 5 ) { /* v2.03: EBP/RBP/R13/R13D? */
676 if( mod_field == MOD_00 ) {
677 mod_field = MOD_01;
678 }
679 }
680 /* s-i-b is present ( r/m = 100b ) */
681 rm_field |= RM_SIB;
682 CodeInfo->sib = ( ss | idx_reg << 3 | base_reg );
683 #if AMD64_SUPPORT
684 rex = (bit3_idx << 1) + (bit3_base); /* set REX_X + REX_B */
685 #endif
686 seg_override( CodeInfo, base, sym, FALSE );
687 } /* end switch(index) */
688 #if AMD64_SUPPORT
689 DebugMsg1(("set_rm_sib, indirect, base+index: mod_field=%X, rm_field=%X, rex=%X\n", mod_field, rm_field, rex ));
690 #else
691 DebugMsg1(("set_rm_sib, indirect, base+index: rm_field=%X\n", rm_field ));
692 #endif
693 }
694 if( CurrOpnd == OPND2 ) {
695 /* shift the register field to left by 3 bit */
696 CodeInfo->rm_byte = mod_field | ( rm_field << 3 ) | ( CodeInfo->rm_byte & BIT_012 );
697 #if AMD64_SUPPORT
698 /* v2.02: exchange B and R, keep X */
699 //CodeInfo->prefix.rex |= (rex >> 2 );
700 CodeInfo->prefix.rex |= ( ( rex >> 2 ) | ( rex & REX_X ) | (( rex & 1) << 2 ) );
701 #endif
702 } else if( CurrOpnd == OPND1 ) {
703 CodeInfo->rm_byte = mod_field | rm_field;
704 #if AMD64_SUPPORT
705 CodeInfo->prefix.rex |= rex;
706 #endif
707 }
708 return( NOT_ERROR );
709 }
710
711 /* override handling
712 * called by
713 * - process_branch()
714 * - idata_fixup()
715 * - memory_operand() (CodeInfo != NULL)
716 * - data_item()
717 * 1. If it's a segment register, set CodeInfo->prefix.RegOverride.
718 * 2. Set global variable SegOverride if it's a SEG/GRP symbol
719 * (or whatever is assumed for the segment register)
720 */
SetSegOverride(const struct expr * opndx,struct code_info * CodeInfo)721 ret_code SetSegOverride( const struct expr *opndx, struct code_info *CodeInfo )
722 /*****************************************************************************/
723 {
724 struct asym *sym;
725
726 if( opndx->override != NULL ) {
727 if( opndx->override->token == T_REG ) {
728 int temp = GetRegNo( opndx->override->tokval );
729 if ( SegAssumeTable[temp].error ) {
730 DebugMsg(("SetSegOverride: assume error, reg=%u\n", temp ));
731 return( EmitError( USE_OF_REGISTER_ASSUMED_TO_ERROR ) );
732 }
733 #if AMD64_SUPPORT
734 /* ES,CS,SS and DS overrides are invalid in 64-bit */
735 if ( CodeInfo && CodeInfo->Ofssize == USE64 && temp < ASSUME_FS ) {
736 return( EmitError( ILLEGAL_USE_OF_SEGMENT_REGISTER ) );
737 }
738 #endif
739 sym = GetOverrideAssume( temp );
740 if ( CodeInfo ) {
741 /* hack: save the previous reg override value (needed for CMPS) */
742 LastRegOverride = CodeInfo->prefix.RegOverride;
743 CodeInfo->prefix.RegOverride = temp;
744 }
745 } else {
746 sym = SymSearch( opndx->override->string_ptr );
747 }
748 DebugMsg1(("SetSegOverride: sym=%s, type=%u\n", sym ? sym->name : "NULL", sym ? sym->state : 0 ));
749 if ( sym && ( sym->state == SYM_GRP || sym->state == SYM_SEG ))
750 SegOverride = sym;
751 }
752 return( NOT_ERROR );
753 }
754
755 /* get an immediate operand without a fixup.
756 * output:
757 * - ERROR: error
758 * - NOT_ERROR: ok,
759 * CodeInfo->opnd_type[CurrOpnd] = OP_Ix
760 * CodeInfo->data[CurrOpnd] = value
761 * CodeInfo->prefix.opsiz
762 * CodeInfo->iswide
763 */
idata_nofixup(struct code_info * CodeInfo,unsigned CurrOpnd,const struct expr * opndx)764 static ret_code idata_nofixup( struct code_info *CodeInfo, unsigned CurrOpnd, const struct expr *opndx )
765 /******************************************************************************************************/
766 {
767 enum operand_type op_type;
768 int_32 value;
769 int size;
770
771 DebugMsg1(("idata_nofixup( CurrOpnd=%u ) enter [opnd kind=%u mem_type=%Xh value=%" I64_SPEC "X]\n", CurrOpnd, opndx->kind, opndx->mem_type, opndx->value64));
772
773 /* jmp/call/jxx/loop/jcxz/jecxz? */
774 if( IS_ANY_BRANCH( CodeInfo->token ) ) {
775 return( process_branch( CodeInfo, CurrOpnd, opndx ) );
776 }
777 value = opndx->value;
778 CodeInfo->opnd[CurrOpnd].data32l = value;
779
780 #if AMD64_SUPPORT
781 /* 64bit immediates are restricted to MOV <reg>,<imm64>
782 */
783 if ( opndx->hlvalue != 0 ) { /* magnitude > 64 bits? */
784 DebugMsg1(("idata_nofixup: error, hlvalue=%" I64_SPEC "X\n", opndx->hlvalue ));
785 return( EmitConstError( opndx ) );
786 }
787 /* v2.03: handle QWORD type coercion here as well!
788 * This change also reveals an old problem in the expression evaluator:
789 * the mem_type field is set whenever a (simple) type token is found.
790 * It should be set ONLY when the type is used in conjuction with the
791 * PTR operator!
792 * current workaround: query the 'explicit' flag.
793 */
794 //if ( opndx->value64 <= minintvalues[0] || opndx->value64 > maxintvalues[0] ) {
795 /* use long format of MOV for 64-bit if value won't fit in a signed DWORD */
796 if ( CodeInfo->Ofssize == USE64 &&
797 CodeInfo->token == T_MOV &&
798 CurrOpnd == OPND2 &&
799 ( CodeInfo->opnd[OPND1].type & OP_R64 ) &&
800 /* v2.14: don't use LONG_MAX/MIN, won't work in 64-bit unix */
801 //( opndx->value64 > LONG_MAX || opndx->value64 < LONG_MIN ||
802 ( opndx->value64 > INT32_MAX || opndx->value64 < INT32_MIN ||
803 (opndx->explicit && ( opndx->mem_type == MT_QWORD || opndx->mem_type == MT_SQWORD ) ) ) ) {
804 // CodeInfo->iswide = 1; /* has been set by first operand already */
805 CodeInfo->opnd[CurrOpnd].type = OP_I64;
806 CodeInfo->opnd[CurrOpnd].data32h = opndx->hvalue;
807 return( NOT_ERROR );
808 }
809 if ( opndx->value64 <= minintvalues[0] || opndx->value64 > maxintvalues[0] ) {
810 DebugMsg1(("idata_nofixup: error, hvalue=%" I32_SPEC "Xh\n", opndx->hvalue ));
811 return( EmitConstError( opndx ) );
812 }
813 #endif
814
815 /* v2.06: code simplified.
816 * to be fixed: the "wide" bit should not be set here!
817 * Problem: the "wide" bit isn't set in memory_operand(),
818 * probably because of the instructions which accept both
819 * signed and unsigned arguments (ADD, CMP, ... ).
820 */
821
822 if ( opndx->explicit ) {
823 /* size coercion for immediate value */
824 CodeInfo->const_size_fixed = TRUE;
825 size = SizeFromMemtype( opndx->mem_type,
826 opndx->Ofssize,
827 opndx->type );
828 /* don't check if size and value are compatible. */
829 switch ( size ) {
830 case 1: op_type = OP_I8; break;
831 case 2: op_type = OP_I16; break;
832 case 4: op_type = OP_I32; break;
833 default:
834 DebugMsg1(("idata_nofixup: invalid size %d for immediate operand\n", size ));
835 return( EmitError( INVALID_INSTRUCTION_OPERANDS ) );
836 }
837 } else {
838 /* use true signed values for BYTE only! */
839 if ( (int_8)value == value )
840 op_type = OP_I8;
841 //else if ( value <= SHRT_MAX && value >= SHRT_MIN )
842 /* v2.04: range FFFF0000-FFFF7FFF is also acceptable for 16-bit */
843 //else if ( value <= USHRT_MAX && value >= SHRT_MIN )
844 /* v2.04b: JWASMR needs a 1L */
845 //else if( value <= USHRT_MAX && value >= - (USHRT_MAX+1) )
846 /* v2.07: JWASMR needs 0L before the - op */
847 //else if( value <= USHRT_MAX && value >= - USHRT_MAX )
848 else if( value <= USHRT_MAX && value >= 0L - USHRT_MAX )
849 op_type = OP_I16;
850 else {
851 op_type = OP_I32;
852 }
853 }
854
855 switch ( CodeInfo->token ) {
856 case T_PUSH:
857 if ( opndx->explicit == FALSE ) {
858 if ( CodeInfo->Ofssize > USE16 && op_type == OP_I16 )
859 op_type = OP_I32;
860 }
861 if ( op_type == OP_I16 )
862 CodeInfo->prefix.opsiz = OPSIZE16( CodeInfo );
863 else if ( op_type == OP_I32 )
864 CodeInfo->prefix.opsiz = OPSIZE32( CodeInfo );
865 break;
866 case T_PUSHW:
867 if ( op_type != OP_I32 ) {
868 op_type = OP_I16;
869 if( (int_8)value == (int_16)value ) {
870 op_type = OP_I8;
871 }
872 }
873 break;
874 case T_PUSHD:
875 if ( op_type == OP_I16 )
876 op_type = OP_I32;
877 break;
878 }
879
880 /* v2.11: set the wide-bit if a mem_type size of > BYTE is set???
881 * actually, it should only be set if immediate is second operand
882 * ( and first operand is a memory ref with a size > 1 )
883 */
884 if ( CurrOpnd == OPND2 )
885 if ( !(CodeInfo->mem_type & MT_SPECIAL) && ( CodeInfo->mem_type & MT_SIZE_MASK ) )
886 CodeInfo->iswide = 1;
887
888 CodeInfo->opnd[CurrOpnd].type = op_type;
889 DebugMsg1(("idata_nofixup exit, op_type=%" I32_SPEC "X\n", op_type ));
890 return( NOT_ERROR );
891 }
892
893 /* get an immediate operand with a fixup.
894 * output:
895 * - ERROR: error
896 * - NOT_ERROR: ok,
897 * CodeInfo->opnd_type[CurrOpnd] = OP_Ix
898 * CodeInfo->data[CurrOpnd] = value
899 * CodeInfo->InsFixup[CurrOpnd] = fixup
900 * CodeInfo->mem_type
901 * CodeInfo->prefix.opsiz
902 * to be fixed: don't modify CodeInfo->mem_type here!
903 */
idata_fixup(struct code_info * CodeInfo,unsigned CurrOpnd,struct expr * opndx)904 ret_code idata_fixup( struct code_info *CodeInfo, unsigned CurrOpnd, struct expr *opndx )
905 /***************************************************************************************/
906 {
907 //struct fixup *fixup;
908 enum fixup_types fixup_type;
909 enum fixup_options fixup_option = OPTJ_NONE;
910 int size;
911 uint_8 Ofssize; /* 1=32bit, 0=16bit offset for fixup */
912
913 DebugMsg1(("idata_fixup( CurrOpnd=%u ) enter [opndx.kind=%u mem_type=%Xh, CodeInfo.mem_type=%Xh]\n", CurrOpnd, opndx->kind, opndx->mem_type, CodeInfo->mem_type));
914
915 /* jmp/call/jcc/loopcc/jxcxz? */
916 if( IS_ANY_BRANCH( CodeInfo->token ) ) {
917 return( process_branch( CodeInfo, CurrOpnd, opndx ) );
918 }
919 CodeInfo->opnd[CurrOpnd].data32l = opndx->value;
920
921 if ( opndx->Ofssize != USE_EMPTY ) {
922 Ofssize = opndx->Ofssize;
923 } else if( opndx->sym == NULL ) { /* v2.15: branch added */
924 SetSegOverride( opndx, NULL );
925 if ( SegOverride )
926 Ofssize = GetSymOfssize( SegOverride );
927 } else if( ( opndx->sym->state == SYM_SEG )
928 || ( opndx->sym->state == SYM_GRP )
929 || ( opndx->instr == T_SEG ) ) {
930 Ofssize = USE16;
931 } else if( opndx->is_abs ) { /* an (external) absolute symbol? */
932 Ofssize = USE16;
933 } else {
934 Ofssize = GetSymOfssize( opndx->sym );
935 }
936
937 if( opndx->instr == T_SHORT ) {
938 /* short works for branch instructions only */
939 return( EmitErr( INVALID_INSTRUCTION_OPERANDS ) );
940 }
941
942 /* the code below should be rewritten.
943 * - an address operator ( OFFSET, LROFFSET, IMAGEREL, SECTIONREL,
944 * LOW, HIGH, LOWWORD, HIGHWORD, LOW32, HIGH32, SEG ) should not
945 * force a magnitude, but may set a minimal magnitude - and the
946 * fixup type, of course.
947 * - check if Codeinfo->mem_type really has to be set here!
948 */
949
950 /* v2.06: added */
951 /* v2.10: modified */
952 //if ( opndx->explicit ) {
953 if ( opndx->explicit && !opndx->is_abs ) {
954 CodeInfo->const_size_fixed = TRUE;
955 if ( CodeInfo->mem_type == MT_EMPTY )
956 CodeInfo->mem_type = opndx->mem_type;
957 }
958 /* v2.03: don't ignore a "NEAR32 ptr" qualifier */
959 //if ( CodeInfo->mem_type == MT_EMPTY && CurrOpnd > OPND1 ) {
960 if ( CodeInfo->mem_type == MT_EMPTY && CurrOpnd > OPND1 && opndx->Ofssize == USE_EMPTY ) {
961 size = OperandSize( CodeInfo->opnd[OPND1].type, CodeInfo );
962 /* may be a forward reference, so wait till pass 2 */
963 if( Parse_Pass > PASS_1 && opndx->instr != EMPTY ) {
964 switch ( opndx->instr ) {
965 case T_SEG: /* v2.04a: added */
966 if( size && (size < 2 ) ) {
967 return( EmitErr( OPERANDS_MUST_BE_THE_SAME_SIZE, size, 2 ) );
968 }
969 break;
970 case T_OFFSET:
971 case T_LROFFSET:
972 #if IMAGERELSUPP
973 case T_IMAGEREL:
974 #endif
975 #if SECTIONRELSUPP
976 case T_SECTIONREL:
977 #endif
978 if( size && (size < 2 || ( Ofssize && size < 4 ))) {
979 return( EmitErr( OPERANDS_MUST_BE_THE_SAME_SIZE, size, ( 2 << Ofssize ) ) );
980 }
981 }
982 }
983 switch ( size ) {
984 case 1:
985 /* v2.05: if () added */
986 if ( opndx->is_abs || opndx->instr == T_LOW || opndx->instr == T_HIGH )
987 CodeInfo->mem_type = MT_BYTE;
988 break;
989 case 2:
990 /* v2.05: if () added */
991 if ( opndx->is_abs ||
992 CodeInfo->Ofssize == USE16 ||
993 opndx->instr == T_LOWWORD ||
994 opndx->instr == T_HIGHWORD )
995 CodeInfo->mem_type = MT_WORD;
996 break;
997 case 4:
998 CodeInfo->mem_type = MT_DWORD;
999 break;
1000 #if AMD64_SUPPORT
1001 case 8:
1002 /* v2.05: it's questionable if size 8 is a good assumption for an
1003 * immediate constant. It's valid for MOV <reg>, <imm> only.
1004 */
1005 //case 8: CodeInfo->mem_type = MT_QWORD;break;
1006 /* v2.05a: added */
1007 if ( Ofssize == USE64 ) {
1008 if ( CodeInfo->token == T_MOV &&
1009 ( CodeInfo->opnd[OPND1].type & OP_R64 ) )
1010 CodeInfo->mem_type = MT_QWORD;
1011 else if ( opndx->instr == T_LOW32 || opndx->instr == T_HIGH32 )
1012 /* v2.10:added; LOW32/HIGH32 in expreval.c won't set mem_type anymore. */
1013 CodeInfo->mem_type = MT_DWORD;
1014 }
1015 break;
1016 #endif
1017 }
1018 }
1019 if ( CodeInfo->mem_type == MT_EMPTY ) {
1020 if( opndx->is_abs ) {
1021 //if( opndx->mem_type != MT_EMPTY && opndx->mem_type != MT_ABS ) {
1022 if( opndx->mem_type != MT_EMPTY ) {
1023 CodeInfo->mem_type = opndx->mem_type;
1024 } else if ( CodeInfo->token == T_PUSHW ) { /* v2.10: special handling PUSHW */
1025 CodeInfo->mem_type = MT_WORD;
1026 } else {
1027 CodeInfo->mem_type = ( IS_OPER_32( CodeInfo ) ? MT_DWORD : MT_WORD );
1028 }
1029 } else {
1030 switch ( CodeInfo->token ) {
1031 case T_PUSHW:
1032 case T_PUSHD:
1033 case T_PUSH:
1034 /* for forward reference, assume BYTE */
1035 /* v2.02: don't assume BYTE if it is SEG/GRP */
1036 //if ( opndx->mem_type == MT_EMPTY ) {
1037 /* v2.07: added cases IMAGEREL and SECTIONREL */
1038 if ( opndx->mem_type == MT_EMPTY ) {
1039 switch( opndx->instr ) {
1040 case EMPTY:
1041 case T_LOW:
1042 case T_HIGH:
1043 opndx->mem_type = MT_BYTE;
1044 break;
1045 case T_LOWWORD: /*v2.12: added */
1046 case T_HIGHWORD: /*v2.12: added */
1047 opndx->mem_type = MT_WORD;
1048 break;
1049 case T_LOW32: /* v2.10: added - low32_op() doesn't set mem_type anymore. */
1050 #if IMAGERELSUPP
1051 case T_IMAGEREL:
1052 #endif
1053 #if SECTIONRELSUPP
1054 case T_SECTIONREL:
1055 #endif
1056 opndx->mem_type = MT_DWORD;
1057 break;
1058 };
1059 }
1060 /* default: push offset only */
1061 /* for PUSH + undefined symbol, assume BYTE */
1062 if ( opndx->mem_type == MT_FAR && ( opndx->explicit == FALSE ) )
1063 opndx->mem_type = MT_NEAR;
1064 /* v2.04: curly brackets added */
1065 if ( CodeInfo->token == T_PUSHW ) {
1066 if ( SizeFromMemtype( opndx->mem_type, Ofssize, opndx->type ) < 2 )
1067 opndx->mem_type = MT_WORD;
1068 } else if ( CodeInfo->token == T_PUSHD ) {
1069 if ( SizeFromMemtype( opndx->mem_type, Ofssize, opndx->type ) < 4 )
1070 opndx->mem_type = MT_DWORD;
1071 }
1072 break;
1073 }
1074 /* if a WORD size is given, don't override it with */
1075 /* anything what might look better at first glance */
1076 if( opndx->mem_type != MT_EMPTY )
1077 CodeInfo->mem_type = opndx->mem_type;
1078 /* v2.15: check for sym==NULL */
1079 /* v2.04: assume BYTE size if symbol is undefined */
1080 //else if ( opndx->sym->state == SYM_UNDEFINED ) {
1081 else if ( opndx->sym && opndx->sym->state == SYM_UNDEFINED ) {
1082 CodeInfo->mem_type = MT_BYTE;
1083 fixup_option = OPTJ_PUSH;
1084 } else
1085 #if AMD64_SUPPORT
1086 /* v2.06d: changed */
1087 CodeInfo->mem_type = ( Ofssize == USE64 ? MT_QWORD : Ofssize == USE32 ? MT_DWORD : MT_WORD );
1088 #else
1089 CodeInfo->mem_type = ( Ofssize > USE16 ? MT_DWORD : MT_WORD );
1090 #endif
1091 }
1092 }
1093 size = SizeFromMemtype( CodeInfo->mem_type, Ofssize, NULL );
1094 switch( size ) {
1095 case 1:
1096 CodeInfo->opnd[CurrOpnd].type = OP_I8;
1097 CodeInfo->prefix.opsiz = FALSE; /* v2.10: reset opsize is not really a good idea - might have been set by previous operand */
1098 break;
1099 case 2: CodeInfo->opnd[CurrOpnd].type = OP_I16; CodeInfo->prefix.opsiz = OPSIZE16( CodeInfo ); break;
1100 case 4: CodeInfo->opnd[CurrOpnd].type = OP_I32; CodeInfo->prefix.opsiz = OPSIZE32( CodeInfo ); break;
1101 #if AMD64_SUPPORT
1102 case 8:
1103 /* v2.05: do only assume size 8 if the constant won't fit in 4 bytes. */
1104 /* v2.14: don't use LONG_MAX/MIN, won't work in 64-bit unix */
1105 //if ( opndx->value64 > LONG_MAX || opndx->value64 < LONG_MIN ||
1106 if ( opndx->value64 > INT32_MAX || opndx->value64 < INT32_MIN ||
1107 (opndx->explicit && ( opndx->mem_type & MT_SIZE_MASK ) == 7 ) ) {
1108 CodeInfo->opnd[CurrOpnd].type = OP_I64;
1109 CodeInfo->opnd[CurrOpnd].data32h = opndx->hvalue;
1110 //} else if ( Ofssize == USE64 ) { /* v2.11: assume 64-bit only for OFFSET or MOV r64, xxx */
1111 } else if ( Ofssize == USE64 && ( opndx->instr == T_OFFSET || ( CodeInfo->token == T_MOV && ( CodeInfo->opnd[OPND1].type & OP_R64 ) ) ) ) {
1112 /* v2.06d: in 64-bit, ALWAYS set OP_I64, so "mov m64, ofs" will fail,
1113 * This was accepted in v2.05-v2.06c)
1114 */
1115 CodeInfo->opnd[CurrOpnd].type = OP_I64;
1116 CodeInfo->opnd[CurrOpnd].data32h = opndx->hvalue;
1117 } else {
1118 CodeInfo->opnd[CurrOpnd].type = OP_I32;
1119 }
1120 CodeInfo->prefix.opsiz = OPSIZE32( CodeInfo );
1121 break;
1122 #endif
1123 #ifdef DEBUG_OUT
1124 default:
1125 DebugMsg1(("idata_fixup, unexpected size %u\n", size ));
1126 /**/myassert( 0 );
1127 #endif
1128 }
1129
1130 /* set fixup_type */
1131
1132 if( opndx->instr == T_SEG ) {
1133 fixup_type = FIX_SEG;
1134 DebugMsg1(("idata_fixup, fixup_type=SEG\n" ));
1135 } else if( CodeInfo->mem_type == MT_BYTE ) {
1136 DebugMsg1(("idata_fixup, mem_type=BYTE\n" ));
1137 if ( opndx->instr == T_HIGH ) {
1138 DebugMsg1(("idata_fixup, fixup_type=HIBYTE\n" ));
1139 fixup_type = FIX_HIBYTE;
1140 } else {
1141 DebugMsg1(("idata_fixup, fixup_type=OFF8\n" ));
1142 fixup_type = FIX_OFF8;
1143 }
1144 #if 0
1145 } else if( CodeInfo->mem_type == MT_FAR ) {
1146 /* v2.04: to be tested. this code is most likely obsolete.
1147 * There's never a PTR16|PTR32 fixup here. Far JMP/CALL are handled
1148 * elsewhere, and data items also.
1149 */
1150 /* temporary */
1151 printf("idata_fixup: MT_FAR occured at %s:%" I32_SPEC "u\n", CurrFName[ASM], LineNumber );
1152 fixup_type = ( Ofssize ) ? FIX_PTR32 : FIX_PTR16;
1153 CodeInfo->isfar = TRUE; /* needed for mark_fixupp() */
1154 if ( opndx->Ofssize != USE_EMPTY )
1155 CodeInfo->Ofssize = opndx->Ofssize;
1156 #endif
1157 } else if( IS_OPER_32( CodeInfo ) ) {
1158 #if AMD64_SUPPORT
1159 /* v2.06: changed */
1160 //if ( Ofssize == USE64 && CodeInfo->mem_type == MT_QWORD )
1161 /* v2.10: changed */
1162 //if ( CodeInfo->opnd[CurrOpnd].type == OP_I64 )
1163 if ( CodeInfo->opnd[CurrOpnd].type == OP_I64 && ( opndx->instr == EMPTY || opndx->instr == T_OFFSET ) ) {
1164 DebugMsg1(("idata_fixup, fixup_type=OFF64\n" ));
1165 fixup_type = FIX_OFF64;
1166 } else
1167 #endif
1168 /* v2.04: changed, no longer depends on OfsSize */
1169 /* v2.05a: changed, so size==8 won't get a FIX_OFF16 type */
1170 //if ( size == 4 )
1171 if ( size >= 4 && opndx->instr != T_LOWWORD ) {
1172 /* v2.06: added branch for PTR16 fixup.
1173 * it's only done if type coercion is FAR (Masm-compat)
1174 */
1175 if ( opndx->explicit && Ofssize == USE16 && opndx->mem_type == MT_FAR ) {
1176 DebugMsg1(("idata_fixup, fixup_type=PTR16\n" ));
1177 fixup_type = FIX_PTR16;
1178 } else {
1179 DebugMsg1(("idata_fixup, fixup_type=OFF32\n" ));
1180 fixup_type = FIX_OFF32;
1181 #if AMD64_SUPPORT
1182 if ( Ofssize == USE64 && Parse_Pass == PASS_2 )
1183 EmitWarn( 3, ADDR32_FIXUP_FOR_64BIT_LABEL );
1184 #endif
1185 }
1186 } else {
1187 DebugMsg1(("idata_fixup, fixup_type=OFF16 (1)\n" ));
1188 fixup_type = FIX_OFF16;
1189 }
1190 } else {
1191 /* v2.04: changed, no longer depends on OfsSize */
1192 //if ( CodeInfo->mem_type == MT_DWORD ) {
1193 /* fixme !!!! warning
1194 * operand size is 16bit
1195 * but fixup is 32-bit */
1196 // fixup_type = FIX_OFF32;
1197 //} else
1198 DebugMsg1(("idata_fixup, fixup_type=OFF16 (2)\n" ));
1199 fixup_type = FIX_OFF16;
1200 }
1201 /* v2.04: 'if' added, don't set W bit if size == 1
1202 * code example:
1203 * extern x:byte
1204 * or al,x
1205 * v2.11: set wide bit only if immediate is second operand.
1206 * and first operand is a memory reference with size > 1
1207 */
1208 //if ( size != 1 )
1209 if ( CurrOpnd == OPND2 && size != 1 )
1210 CodeInfo->iswide = 1;
1211
1212 SetSegOverride( opndx, NULL ); /* set SegOverride global var */
1213
1214 /* set frame type in variables Frame_Type and Frame_Datum for fixup creation */
1215 if ( ModuleInfo.offsettype == OT_SEGMENT &&
1216 ( opndx->instr == T_OFFSET || opndx->instr == T_SEG ))
1217 set_frame2( opndx->sym );
1218 else
1219 set_frame( opndx->sym );
1220
1221 //DebugMsg1(("idata_fixup: calling CreateFixup(%s, %u)\n", opndx->sym->name, fixup_type ));
1222 CodeInfo->opnd[CurrOpnd].InsFixup = CreateFixup( opndx->sym, fixup_type, fixup_option );
1223
1224 if ( opndx->instr == T_LROFFSET )
1225 CodeInfo->opnd[CurrOpnd].InsFixup->loader_resolved = TRUE;
1226
1227 #if IMAGERELSUPP
1228 if ( opndx->instr == T_IMAGEREL && fixup_type == FIX_OFF32 )
1229 CodeInfo->opnd[CurrOpnd].InsFixup->type = FIX_OFF32_IMGREL;
1230 #endif
1231 #if SECTIONRELSUPP
1232 if ( opndx->instr == T_SECTIONREL && fixup_type == FIX_OFF32 )
1233 CodeInfo->opnd[CurrOpnd].InsFixup->type = FIX_OFF32_SECREL;
1234 #endif
1235 DebugMsg1(("idata_fixup exit [CodeInfo.mem_type=%Xh Ofssize=%u opsiz=%u fixup.type=%u fixup.frame=%d]\n",
1236 CodeInfo->mem_type, CodeInfo->Ofssize, CodeInfo->prefix.opsiz,
1237 CodeInfo->opnd[CurrOpnd].InsFixup->type, CodeInfo->opnd[CurrOpnd].InsFixup->frame_type ));
1238
1239 return( NOT_ERROR );
1240 }
1241
1242 /* convert MT_PTR to MT_WORD, MT_DWORD, MT_FWORD, MT_QWORD.
1243 * MT_PTR cannot be set explicitely (by the PTR operator),
1244 * so this value must come from a label or a structure field.
1245 * (above comment is most likely plain wrong, see 'PF16 ptr [reg]'!
1246 * This code needs cleanup!
1247 */
SetPtrMemtype(struct code_info * CodeInfo,struct expr * opndx)1248 static void SetPtrMemtype( struct code_info *CodeInfo, struct expr *opndx )
1249 /*************************************************************************/
1250 {
1251 struct asym *sym = opndx->sym;
1252 int size = 0;
1253
1254 if ( opndx->mbr ) /* the mbr field has higher priority */
1255 sym = opndx->mbr;
1256
1257 /* v2.10: the "explicit" condition is now handled FIRST */
1258 #if 1 /* v2.0: handle PF16 ptr [ebx], which didn't work in v1.96 */
1259 if ( opndx->explicit && opndx->type ) {
1260 size = opndx->type->total_size;
1261 CodeInfo->isfar = opndx->type->isfar;
1262 } else
1263 #endif
1264 if ( sym ) {
1265 if ( sym->type ) {
1266 size = sym->type->total_size;
1267 CodeInfo->isfar = sym->type->isfar;
1268
1269 /* there's an ambiguity with pointers of size DWORD,
1270 since they can be either NEAR32 or FAR16 */
1271 if ( size == 4 && sym->type->Ofssize != CodeInfo->Ofssize )
1272 opndx->Ofssize = sym->type->Ofssize;
1273
1274 } else if ( sym->mem_type == MT_PTR ) {
1275 size = SizeFromMemtype( sym->isfar ? MT_FAR : MT_NEAR, sym->Ofssize, NULL );
1276 CodeInfo->isfar = sym->isfar;
1277 } else {
1278 if ( sym->isarray )
1279 size = sym->total_size / sym->total_length;
1280 else
1281 size = sym->total_size;
1282 }
1283 } else {
1284 if ( SIZE_DATAPTR & ( 1 << ModuleInfo.model ) ) {
1285 DebugMsg1(("SetPtrMemtype: model with FAR data pointers\n" ));
1286 size = 2;
1287 }
1288 size += (2 << ModuleInfo.defOfssize );
1289 }
1290 if ( size )
1291 MemtypeFromSize( size, &opndx->mem_type );
1292 DebugMsg1(("SetPtrMemtype: size=%u, new memtype=0x%x\n", size, opndx->mem_type ));
1293 }
1294
1295 /*
1296 * set fields in CodeInfo:
1297 * - mem_type
1298 * - prefix.opsiz
1299 * - prefix.rex REX_W
1300 * called by memory_operand()
1301 */
Set_Memtype(struct code_info * CodeInfo,enum memtype mem_type)1302 static void Set_Memtype( struct code_info *CodeInfo, enum memtype mem_type )
1303 /**************************************************************************/
1304 {
1305 if( CodeInfo->token == T_LEA )
1306 return;
1307
1308 /* v2.05: changed. Set "data" types only. */
1309 if( mem_type == MT_EMPTY || mem_type == MT_TYPE ||
1310 mem_type == MT_NEAR || mem_type == MT_FAR )
1311 return;
1312
1313 CodeInfo->mem_type = mem_type;
1314
1315 if( CodeInfo->Ofssize > USE16 ) {
1316 /* if we are in use32 mode, we have to add OPSIZ prefix for
1317 * most of the 386 instructions when operand has type WORD.
1318 * Exceptions ( MOVSX and MOVZX ) are handled in check_size().
1319 */
1320 if ( IS_MEM_TYPE( mem_type, WORD ) )
1321 CodeInfo->prefix.opsiz = TRUE;
1322 #if AMD64_SUPPORT
1323 /*
1324 * set rex Wide bit if a QWORD operand is found (not for FPU/MMX/SSE instr).
1325 * This looks pretty hackish now and is to be cleaned!
1326 * v2.01: also had issues with SSE2 MOVSD/CMPSD, now fixed!
1327 */
1328 /* v2.06: with AVX, SSE tokens may exist twice, one
1329 * for "legacy", the other for VEX encoding!
1330 */
1331 else if ( IS_MEMTYPE_SIZ( mem_type, sizeof( uint_64 ) ) ) {
1332 switch( CodeInfo->token ) {
1333 case T_PUSH: /* for PUSH/POP, REX_W isn't needed (no 32-bit variants in 64-bit mode) */
1334 case T_POP:
1335 case T_CMPXCHG8B:
1336 #if VMXSUPP
1337 case T_VMPTRLD:
1338 case T_VMPTRST:
1339 case T_VMCLEAR:
1340 case T_VMXON:
1341 #endif
1342 break;
1343 default:
1344 /* don't set REX for opcodes that accept memory operands
1345 * of any size.
1346 */
1347 if ( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[OPND1] == OP_M_ANY ) {
1348 //printf( "Set_Memtype: OP_M_ANY detected, file=%s, instr=%s\n", CurrFName[ASM], GetResWName( CodeInfo->token, NULL ) );
1349 break;
1350 }
1351 /* don't set REX for FPU opcodes */
1352 if ( CodeInfo->pinstr->cpu & P_FPU_MASK )
1353 break;
1354 /* don't set REX for - most - MMX/SSE opcodes */
1355 if ( CodeInfo->pinstr->cpu & P_EXT_MASK ) {
1356 switch ( CodeInfo->token ) {
1357 /* [V]CMPSD and [V]MOVSD are also candidates,
1358 * but currently they are handled in HandleStringInstructions()
1359 */
1360 case T_CVTSI2SD: /* v2.06: added */
1361 case T_CVTSI2SS: /* v2.06: added */
1362 case T_PEXTRQ: /* v2.06: added */
1363 case T_PINSRQ: /* v2.06: added */
1364 case T_MOVD:
1365 #if AVXSUPP
1366 case T_VCVTSI2SD:
1367 case T_VCVTSI2SS:
1368 case T_VPEXTRQ:
1369 case T_VPINSRQ:
1370 case T_VMOVD:
1371 #endif
1372 CodeInfo->prefix.rex |= REX_W;
1373 break;
1374 default:
1375 break;
1376 }
1377 }
1378 else
1379 CodeInfo->prefix.rex |= REX_W;
1380 }
1381 }
1382 #endif
1383
1384 /* v2.05: IS_MEM_TYPE() doesn't work with MT_REALx */
1385 //} else if( CodeInfo->Ofssize == USE16 && ( IS_MEM_TYPE( mem_type, DWORD ) ) ) {
1386 } else {
1387 if( IS_MEMTYPE_SIZ( mem_type, sizeof(uint_32) ) ) {
1388
1389 /* in 16bit mode, a DWORD memory access usually requires an OPSIZ
1390 * prefix. A few instructions, which access m16:16 operands,
1391 * are exceptions.
1392 */
1393 switch( CodeInfo->token ) {
1394 case T_LDS:
1395 case T_LES:
1396 case T_LFS:
1397 case T_LGS:
1398 case T_LSS:
1399 case T_CALL: /* v2.0: added */
1400 case T_JMP: /* v2.0: added */
1401 /* in these cases, opsize does NOT need to be changed */
1402 break;
1403 default:
1404 CodeInfo->prefix.opsiz = TRUE;
1405 break;
1406 }
1407 }
1408 #if AMD64_SUPPORT
1409 /* v2.06: added because in v2.05, 64-bit memory operands were
1410 * accepted in 16-bit code
1411 */
1412 else if ( IS_MEMTYPE_SIZ( mem_type, sizeof(uint_64) ) ) {
1413 if ( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[OPND1] == OP_M_ANY ) {
1414 //printf( "Set_Memtype: OP_M_ANY detected, file=%s, instr=%s\n", CurrFName[ASM], GetResWName( CodeInfo->token, NULL ) );
1415 } else if ( CodeInfo->pinstr->cpu & ( P_FPU_MASK | P_EXT_MASK ) ) {
1416 ;
1417 } else if ( CodeInfo->token != T_CMPXCHG8B )
1418 /* setting REX.W will cause an error in codegen */
1419 CodeInfo->prefix.rex |= REX_W;
1420 }
1421 #endif
1422 }
1423 return;
1424 }
1425
1426 /*
1427 * process direct or indirect memory operand
1428 * in: opndx=operand to process
1429 * in: CurrOpnd=no of operand (0=first operand,1=second operand)
1430 * out: CodeInfo->data[]
1431 * out: CodeInfo->opnd_type[]
1432 */
1433
memory_operand(struct code_info * CodeInfo,unsigned CurrOpnd,struct expr * opndx,bool with_fixup)1434 static ret_code memory_operand( struct code_info *CodeInfo, unsigned CurrOpnd, struct expr *opndx, bool with_fixup )
1435 /******************************************************************************************************************/
1436 {
1437 char ss = SCALE_FACTOR_1;
1438 int index;
1439 int base;
1440 int j;
1441 struct asym *sym;
1442 uint_8 Ofssize;
1443 enum fixup_types fixup_type;
1444
1445 DebugMsg1(("memory_operand(opndx.value=%" I32_SPEC "X / sym=%s / memtype=%Xh, with_fixup=%u) enter, [CodeInfo->memtype=%Xh, Ofssize=%u, adrsiz=%u]\n",
1446 opndx->value, opndx->sym ? opndx->sym->name : "NULL", opndx->mem_type, with_fixup, CodeInfo->mem_type, CodeInfo->Ofssize, CodeInfo->prefix.adrsiz ));
1447
1448 /* v211: use full 64-bit value */
1449 //CodeInfo->opnd[CurrOpnd].data = opndx->value;
1450 CodeInfo->opnd[CurrOpnd].data64 = opndx->value64;
1451 CodeInfo->opnd[CurrOpnd].type = OP_M;
1452
1453 sym = opndx->sym;
1454
1455 SetSegOverride( opndx, CodeInfo );
1456
1457 /* change pointer types ( MT_NEAR, MT_FAR, MT_PTR */
1458 /* v2.04a: should not be called if OFFSET was used */
1459 //if ( opndx->mem_type == MT_PTR ) /* this was before v2.04 */
1460 //if ( ( opndx->mem_type & MT_SPECIAL_MASK ) == MT_ADDRESS )
1461 /* v2.05: change reverted */
1462 //if ( ( opndx->mem_type & MT_SPECIAL_MASK ) == MT_ADDRESS && opndx->instr == EMPTY )
1463 if ( opndx->mem_type == MT_PTR )
1464 SetPtrMemtype( CodeInfo, opndx );
1465 else if ( ( opndx->mem_type & MT_SPECIAL_MASK ) == MT_ADDRESS ) {
1466 int size;
1467 if ( opndx->Ofssize == USE_EMPTY && sym )
1468 opndx->Ofssize = GetSymOfssize( sym );
1469 /* v2.09: use opndx->type ( for MT_PROC ) */
1470 //size = SizeFromMemtype( opndx->mem_type, opndx->Ofssize, NULL );
1471 size = SizeFromMemtype( opndx->mem_type, opndx->Ofssize, opndx->type );
1472 MemtypeFromSize( size, &opndx->mem_type );
1473 }
1474
1475 Set_Memtype( CodeInfo, opndx->mem_type );
1476 if( opndx->mbr != NULL ) {
1477 /* if the struct field is just another struct, use it's total size
1478 * to set CodeInfo->mem_type.
1479 */
1480 //if ( opndx->mbr->mem_type == MT_TYPE ) {
1481 /* v2: don't overwrite opndx->mem_type,
1482 * testcase: cmp (dword ptr <struct_field>), 0
1483 */
1484 if ( opndx->mbr->mem_type == MT_TYPE && opndx->mem_type == MT_EMPTY ) {
1485 enum memtype mem_type;
1486 DebugMsg1(("memory_operand: mbr %s has mem_type MT_TYPE, total_size=%u\n", opndx->mbr->name, opndx->mbr->total_size ));
1487 if ( MemtypeFromSize( opndx->mbr->total_size, &mem_type ) == NOT_ERROR )
1488 Set_Memtype( CodeInfo, mem_type );
1489 }
1490 //else /* v2: obsolete */
1491 // Set_Memtype( CodeInfo, opndx->mbr->mem_type );
1492 /* v2.06b: tell codegen that the member is a forward ref */
1493 if ( opndx->mbr->state == SYM_UNDEFINED )
1494 CodeInfo->undef_sym = TRUE;
1495 }
1496
1497 /* instruction-specific handling */
1498 switch ( CodeInfo->token ) {
1499 case T_JMP:
1500 case T_CALL:
1501 /* the 2 branch instructions are peculiar because they
1502 * will work with an unsized label.
1503 */
1504 /* v1.95: convert MT_NEAR/MT_FAR and display error if no type.
1505 * For memory operands, expressions of type MT_NEAR/MT_FAR are
1506 * call [bx+<code_label>]
1507 */
1508 if ( CodeInfo->mem_type == MT_EMPTY ) {
1509 /* with -Zm, no size needed for indirect CALL/JMP */
1510 if ( ModuleInfo.m510 == FALSE &&
1511 ( Parse_Pass > PASS_1 && opndx->sym == NULL ) ) {
1512 DebugMsg1(("memory_operand, JMP/CALL: CodeInfo->memtype=empty, instruction operand must have size\n" ));
1513 return( EmitError( INSTRUCTION_OPERAND_MUST_HAVE_SIZE ) );
1514 }
1515 #if AMD64_SUPPORT
1516 opndx->mem_type = (CodeInfo->Ofssize == USE64) ? MT_QWORD : (CodeInfo->Ofssize == USE32) ? MT_DWORD : MT_WORD;
1517 #else
1518 opndx->mem_type = (CodeInfo->Ofssize == USE32) ? MT_DWORD : MT_WORD;
1519 #endif
1520 Set_Memtype( CodeInfo, opndx->mem_type );
1521 DebugMsg1(("memory_operand, JMP/CALL: CodeInfo->memtype set to %Xh\n", CodeInfo->mem_type ));
1522 }
1523 j = SizeFromMemtype( CodeInfo->mem_type, CodeInfo->Ofssize, NULL );
1524 if ( ( j == 1 || j > 6 )
1525 #if AMD64_SUPPORT
1526 && ( CodeInfo->Ofssize != USE64 )
1527 #endif
1528 ) {
1529 /* CALL/JMP possible for WORD/DWORD/FWORD memory operands only */
1530 DebugMsg1(("memory_operand: invalid operand, size=%u\n", j ));
1531 return( EmitError( INVALID_OPERAND_SIZE ) );
1532 }
1533
1534 if( opndx->mem_type == MT_FAR || CodeInfo->mem_type == MT_FWORD ||
1535 #if AMD64_SUPPORT
1536 ( CodeInfo->mem_type == MT_TBYTE && CodeInfo->Ofssize == USE64 ) ||
1537 #endif
1538 ( CodeInfo->mem_type == MT_DWORD &&
1539 (( CodeInfo->Ofssize == USE16 && opndx->Ofssize != USE32 ) ||
1540 ( CodeInfo->Ofssize == USE32 && opndx->Ofssize == USE16 )))) {
1541 CodeInfo->isfar = TRUE;
1542 }
1543 DebugMsg1(("memory_operand: JMP/CALL, CodeInfo->far=%u\n", CodeInfo->isfar ));
1544 break;
1545 }
1546
1547 if ( ( CodeInfo->mem_type & MT_SPECIAL) == 0 ) {
1548 switch ( CodeInfo->mem_type & MT_SIZE_MASK ) {
1549 /* size is encoded 0-based */
1550 case 0: CodeInfo->opnd[CurrOpnd].type = OP_M08; break;
1551 case 1: CodeInfo->opnd[CurrOpnd].type = OP_M16; break;
1552 case 3: CodeInfo->opnd[CurrOpnd].type = OP_M32; break;
1553 case 5: CodeInfo->opnd[CurrOpnd].type = OP_M48; break;
1554 case 7: CodeInfo->opnd[CurrOpnd].type = OP_M64; break;
1555 case 9: CodeInfo->opnd[CurrOpnd].type = OP_M80; break;
1556 case 15: CodeInfo->opnd[CurrOpnd].type = OP_M128; break;
1557 #if AVXSUPP
1558 case 31: CodeInfo->opnd[CurrOpnd].type = OP_M256; break;
1559 #endif
1560 #ifdef DEBUG_OUT
1561 default:
1562 DebugMsg1(("memory_operand: unexpected mem_type=%X\n", CodeInfo->mem_type ));
1563 /**/myassert( 0 );
1564 #endif
1565 }
1566 #if 0 /* v2.06: the wide flag isn't set for memory operands currently, */
1567 if ( CodeInfo->opnd_type[CurrOpnd] & ( OP_M16 | OP_M32 | OP_M64 ) )
1568 CodeInfo->iswide = 1;
1569 #endif
1570 } else if ( CodeInfo->mem_type == MT_EMPTY ) {
1571 /* v2.05: added */
1572 switch ( CodeInfo->token ) {
1573 case T_INC:
1574 case T_DEC:
1575 /* jwasm v1.94-v2.04 accepted unsized operand for INC/DEC */
1576 if ( opndx->sym == NULL ) {
1577 return( EmitError( INSTRUCTION_OPERAND_MUST_HAVE_SIZE ) );
1578 }
1579 break;
1580 case T_PUSH:
1581 case T_POP:
1582 if ( opndx->mem_type == MT_TYPE ) {
1583 return( EmitError( INVALID_INSTRUCTION_OPERANDS ) );
1584 }
1585 break;
1586 }
1587 }
1588
1589 base = ( opndx->base_reg ? opndx->base_reg->tokval : EMPTY );
1590 index = ( opndx->idx_reg ? opndx->idx_reg->tokval : EMPTY );
1591
1592 /* use base + index from here - don't use opndx-> base_reg/idx_reg! */
1593
1594 #if 0 /* v2.10: moved to expreval.c */
1595 if ( sym && sym->state == SYM_STACK ) {
1596 if( base != EMPTY ) {
1597 if( index != EMPTY ) {
1598 /* no free index register */
1599 return( EmitError( MULTIPLE_INDEX_REGISTERS_NOT_ALLOWED ) );
1600 } else {
1601 index = base;
1602 }
1603 }
1604 base = basereg[CodeInfo->Ofssize];
1605 }
1606 #endif
1607
1608 /* check for base registers */
1609
1610 if ( base != EMPTY ) {
1611 if ( ( ( GetValueSp( base ) & OP_R32) && CodeInfo->Ofssize == USE32 ) ||
1612 #if AMD64_SUPPORT
1613 ( ( GetValueSp( base ) & OP_R64) && CodeInfo->Ofssize == USE64 ) ||
1614 #endif
1615 ( ( GetValueSp( base ) & OP_R16) && CodeInfo->Ofssize == USE16 ) )
1616 CodeInfo->prefix.adrsiz = FALSE;
1617 else {
1618 CodeInfo->prefix.adrsiz = TRUE;
1619 #if AMD64_SUPPORT
1620 /* 16bit addressing modes don't exist in long mode */
1621 if ( ( GetValueSp( base ) & OP_R16) && CodeInfo->Ofssize == USE64 ) {
1622 return( EmitError( INVALID_ADDRESSING_MODE_WITH_CURRENT_CPU_SETTING ) );
1623 }
1624 #endif
1625 }
1626 }
1627
1628 /* check for index registers */
1629
1630 if( index != EMPTY ) {
1631 if ( ( ( GetValueSp( index ) & OP_R32) && CodeInfo->Ofssize == USE32 ) ||
1632 #if AMD64_SUPPORT
1633 ( ( GetValueSp( index ) & OP_R64) && CodeInfo->Ofssize == USE64 ) ||
1634 #endif
1635 ( ( GetValueSp( index ) & OP_R16) && CodeInfo->Ofssize == USE16 ) ) {
1636 CodeInfo->prefix.adrsiz = FALSE;
1637 } else {
1638 CodeInfo->prefix.adrsiz = TRUE;
1639 #if AMD64_SUPPORT /* v2.13: check added. see expr6.aso */
1640 /* 16bit addressing modes don't exist in long mode */
1641 if ( ( GetValueSp( index ) & OP_R16) && CodeInfo->Ofssize == USE64 ) {
1642 return( EmitError( INVALID_ADDRESSING_MODE_WITH_CURRENT_CPU_SETTING ) );
1643 }
1644 #endif
1645 }
1646
1647 /* v2.10: register swapping has been moved to expreval.c, index_connect().
1648 * what has remained here is the check if R/ESP is used as index reg.
1649 */
1650 if ( GetRegNo( index ) == 4 ) { /* [E|R]SP? */
1651 DebugMsg(( "memory_operand: error, base regno=%u, index regno=%u, opnd.scale=%u\n", GetRegNo( base ), GetRegNo( index ), opndx->scale ));
1652 //int tmp = index;
1653 if( opndx->scale ) { /* no scale must be set */
1654 EmitErr( CANNOT_BE_USED_AS_INDEX_REGISTER, GetResWName( index, NULL ) );
1655 //return( ERROR );
1656 } else {
1657 //if ( GetRegNo( base ) == 4 ) {
1658 EmitErr( MULTIPLE_BASE_REGISTERS_NOT_ALLOWED );
1659 //return( ERROR );
1660 }
1661 return( ERROR );
1662 /* swap base and index */
1663 //index = base;
1664 //base = tmp;
1665 #if 0
1666 } else if ( Options.masm_compat_gencode && opndx->scale == 0 && GetRegNo( base ) != 4 ) {
1667 /* v2.08: Masm 6+ swaps base and index, even if -Zm is set (Masm 5.1 does NOT swap) */
1668 int tmp = index;
1669 /* swap base and index */
1670 index = base;
1671 base = tmp;
1672 #endif
1673 }
1674
1675 /* 32/64 bit indirect addressing? */
1676 if( ( CodeInfo->Ofssize == USE16 && CodeInfo->prefix.adrsiz == 1 ) ||
1677 #if AMD64_SUPPORT
1678 CodeInfo->Ofssize == USE64 ||
1679 #endif
1680 ( CodeInfo->Ofssize == USE32 && CodeInfo->prefix.adrsiz == 0 ) ) {
1681 if( ( ModuleInfo.curr_cpu & P_CPU_MASK ) >= P_386 ) {
1682 /* scale, 0 or 1->00, 2->40, 4->80, 8->C0 */
1683 switch( opndx->scale ) {
1684 case 0:
1685 case 1: break; /* ss = 00 */
1686 case 2: ss = SCALE_FACTOR_2; break; /* ss = 01 */
1687 case 4: ss = SCALE_FACTOR_4; break; /* ss = 10 */
1688 case 8: ss = SCALE_FACTOR_8; break; /* ss = 11 */
1689 default: /* must be * 1, 2, 4 or 8 */
1690 return( EmitError( SCALE_FACTOR_MUST_BE_1_2_4_OR_8 ) );
1691 }
1692 } else {
1693 /* 286 and down cannot use this memory mode */
1694 return( EmitError( INVALID_ADDRESSING_MODE_WITH_CURRENT_CPU_SETTING ) );
1695 }
1696 } else {
1697 /* v2.01: 16-bit addressing mode. No scale possible */
1698 if ( opndx->scale ) {
1699 return( EmitError( INVALID_USE_OF_REGISTER ) );
1700 }
1701 }
1702 }
1703
1704 if( with_fixup ) {
1705
1706 if( opndx->is_abs ) {
1707 Ofssize = IS_ADDR32( CodeInfo );
1708 } else if ( sym ) {
1709 Ofssize = GetSymOfssize( sym );
1710 } else if ( SegOverride ) {
1711 Ofssize = GetSymOfssize( SegOverride );
1712 } else
1713 Ofssize = CodeInfo->Ofssize;
1714
1715 /* now set fixup_type.
1716 * for direct addressing, the fixup type can easily be set by
1717 * the symbol's offset size.
1718 */
1719 if( base == EMPTY && index == EMPTY ) {
1720 CodeInfo->prefix.adrsiz = ADDRSIZE( CodeInfo->Ofssize, Ofssize );
1721 #if AMD64_SUPPORT
1722 /* v2.13: also check CI->Ofssize. if current segm is 64-bit,
1723 * use 32-bit rel fixups (mixed mode 64-bit mz binary) - ignore Ofssize */
1724 //if ( Ofssize == USE64 )
1725 if ( Ofssize == USE64 || CodeInfo->Ofssize == USE64 )
1726 /* v2.03: override with a segment assumed != FLAT? */
1727 if ( opndx->override != NULL &&
1728 SegOverride != &ModuleInfo.flat_grp->sym )
1729 fixup_type = FIX_OFF32;
1730 else
1731 fixup_type = FIX_RELOFF32;
1732 else
1733 #endif
1734 fixup_type = ( Ofssize ) ? FIX_OFF32 : FIX_OFF16;
1735 DebugMsg1(( "memory_operand: direct addressing, fixup type=%u\n", fixup_type ));
1736 } else {
1737 DebugMsg1(( "memory_operand: CodeInfo->Ofssize=%u/prefix.adrsize=%u, Ofssize=%u\n",
1738 CodeInfo->Ofssize, CodeInfo->prefix.adrsiz, Ofssize ));
1739 #if AMD64_SUPPORT
1740 if( Ofssize == USE64 ) {
1741 fixup_type = FIX_OFF32;
1742 } else
1743 #endif
1744 if( IS_ADDR32( CodeInfo ) ) { /* address prefix needed? */
1745 /* changed for v1.95. Probably more tests needed!
1746 * test case:
1747 * mov eax,[ebx*2-10+offset var] ;code and var are 16bit!
1748 * the old code usually works fine because HiWord of the
1749 * symbol's offset is zero. However, if there's an additional
1750 * displacement which makes the value stored at the location
1751 * < 0, then the target's HiWord becomes <> 0.
1752 */
1753 //fixup_type = ( Ofssize ) ? FIX_OFF32 : FIX_OFF16;
1754 fixup_type = FIX_OFF32;
1755 } else {
1756 fixup_type = FIX_OFF16;
1757 if( Ofssize && Parse_Pass == PASS_2 ) {
1758 /* address size is 16bit but label is 32-bit.
1759 * example: use a 16bit register as base in FLAT model:
1760 * test buff[di],cl */
1761 EmitWarn( 2, WORD_FIXUP_FOR_32BIT_LABEL, sym->name );
1762 }
1763 }
1764 }
1765
1766 #if IMAGERELSUPP || SECTIONRELSUPP /* v2.10: added; IMAGEREL/SECTIONREL for indirect memory operands */
1767 if ( fixup_type == FIX_OFF32 )
1768 if ( opndx->instr == T_IMAGEREL )
1769 fixup_type = FIX_OFF32_IMGREL;
1770 else if ( opndx->instr == T_SECTIONREL )
1771 fixup_type = FIX_OFF32_SECREL;
1772 #endif
1773 /* no fixups are needed for memory operands of string instructions and XLAT/XLATB.
1774 * However, CMPSD and MOVSD are also SSE2 opcodes, so the fixups must be generated
1775 * anyways.
1776 */
1777 if ( CodeInfo->token != T_XLAT && CodeInfo->token != T_XLATB ) {
1778 //DebugMsg1(("memory_operand: calling CreateFixup(%s, fixup=%u) [CodeInfo->memtype=%Xh]\n", sym ? sym->name : "NULL", fixup_type, CodeInfo->mem_type));
1779 CodeInfo->opnd[CurrOpnd].InsFixup = CreateFixup( sym, fixup_type, OPTJ_NONE );
1780 }
1781 }
1782 #ifdef DEBUG_OUT
1783 else
1784 DebugMsg1(("memory_operand: without fixup, CI->Ofssize=%u, adrsize=%u\n", CodeInfo->Ofssize, CodeInfo->prefix.adrsiz ));
1785 #endif
1786
1787 if( set_rm_sib( CodeInfo, CurrOpnd, ss, index, base, sym ) == ERROR ) {
1788 return( ERROR );
1789 }
1790 /* set frame type/data in fixup if one was created */
1791 if ( CodeInfo->opnd[CurrOpnd].InsFixup ) {
1792 CodeInfo->opnd[CurrOpnd].InsFixup->frame_type = Frame_Type;
1793 CodeInfo->opnd[CurrOpnd].InsFixup->frame_datum = Frame_Datum;
1794 }
1795
1796 DebugMsg1(("memory_operand exit, ok, opndx.type/value=%Xh/%Xh, CodeInfo.memtype/rmbyte=%X/%X opndtype=%Xh fix=%Xh\n",
1797 opndx->type, opndx->value, CodeInfo->mem_type, CodeInfo->rm_byte, CodeInfo->opnd[CurrOpnd].type, CodeInfo->opnd[CurrOpnd].InsFixup ));
1798 return( NOT_ERROR );
1799 }
1800
process_address(struct code_info * CodeInfo,unsigned CurrOpnd,struct expr * opndx)1801 static ret_code process_address( struct code_info *CodeInfo, unsigned CurrOpnd, struct expr *opndx )
1802 /**************************************************************************************************/
1803 /*
1804 * parse the memory reference operand
1805 * CurrOpnd is 0 for first operand, 1 for second, ...
1806 * valid return values: NOT_ERROR, ERROR
1807 */
1808 {
1809 if( opndx->indirect ) { /* indirect register operand or stack var */
1810
1811 DebugMsg1(("process_address: INDIRECT, sym=%s mbr=%s ci.adrsiz=%u\n",
1812 opndx->sym ? opndx->sym->name : "NULL",
1813 opndx->mbr ? opndx->mbr->name : "NULL",
1814 CodeInfo->prefix.adrsiz ));
1815 /* if displacement doesn't fit in 32-bits:
1816 * Masm (both ML and ML64) just truncates.
1817 * JWasm throws an error in 64bit mode and
1818 * warns (level 3) in the other modes.
1819 * todo: this check should also be done for direct addressing!
1820 */
1821 if ( opndx->hvalue && ( opndx->hvalue != -1 || opndx->value >= 0 ) ) {
1822 DebugMsg1(("process_address: displacement doesn't fit in 32 bits: %" I64_SPEC "X\n", opndx->value64 ));
1823 #if AMD64_SUPPORT
1824 if ( ModuleInfo.Ofssize == USE64 ) {
1825 return( EmitConstError( opndx ) );
1826 }
1827 #endif
1828 if( Parse_Pass == PASS_1 ) /* v2.13: don't warn multiple times */
1829 EmitWarn( 3, DISPLACEMENT_OUT_OF_RANGE, opndx->value64 );
1830 }
1831 if( opndx->sym == NULL || opndx->sym->state == SYM_STACK ) {
1832 return( memory_operand( CodeInfo, CurrOpnd, opndx, FALSE ) );
1833 }
1834 /* do default processing */
1835
1836 } else if( opndx->instr != EMPTY ) {
1837 /* instr is OFFSET | LROFFSET | SEG | LOW | LOWWORD, ... */
1838 DebugMsg1(("process_address: instr=%s\n", GetResWName( opndx->instr, NULL ) ));
1839 /* v2.15 create fixup if override is given */
1840 //if( opndx->sym == NULL ) { /* better to check opndx->type? */
1841 if( opndx->sym == NULL && ( opndx->override == NULL || opndx->override->token == T_REG )) {
1842 return( idata_nofixup( CodeInfo, CurrOpnd, opndx ) );
1843 } else {
1844 /* allow "lea <reg>, [offset <sym>]" */
1845 if( CodeInfo->token == T_LEA && opndx->instr == T_OFFSET )
1846 return( memory_operand( CodeInfo, CurrOpnd, opndx, TRUE ) );
1847 return( idata_fixup( CodeInfo, CurrOpnd, opndx ) );
1848 }
1849 } else if( opndx->sym == NULL ) { /* direct operand without symbol */
1850 DebugMsg1(("process_address: symbol=NULL\n" ));
1851 if( opndx->override != NULL ) {
1852 /* direct absolute memory without symbol.
1853 DS:[0] won't create a fixup, but
1854 DGROUP:[0] will create one! */
1855 #if AMD64_SUPPORT
1856 /* for 64bit, always create a fixup, since RIP-relative addressing is used
1857 * v2.11: don't create fixup in 64-bit.
1858 */
1859 //if ( opndx->override->token == T_REG && CodeInfo->Ofssize != USE64 )
1860 if ( opndx->override->token == T_REG || CodeInfo->Ofssize == USE64 )
1861 #else
1862 if ( opndx->override->token == T_REG )
1863 #endif
1864 return( memory_operand( CodeInfo, CurrOpnd, opndx, FALSE ) );
1865 else
1866 return( memory_operand( CodeInfo, CurrOpnd, opndx, TRUE ) );
1867 } else {
1868 return( idata_nofixup( CodeInfo, CurrOpnd, opndx ) );
1869 }
1870 } else if( ( opndx->sym->state == SYM_UNDEFINED ) && !opndx->explicit ) {
1871 DebugMsg1(("process_address: sym=SYM_UNDEFINED, name=%s, state=%X\n", opndx->sym->name, opndx->sym->state ));
1872 /* v2.04: unnecessary, the expression evaluator will have emitted an error already */
1873 //if( Parse_Pass != PASS_1 ) {
1874 // EmitErr( SYMBOL_NOT_DEFINED, opndx->sym->name );
1875 // return( ERROR );
1876 //}
1877 /* undefined symbol, it's not possible to determine
1878 * operand type and size currently. However, for backpatching
1879 * a fixup should be created.
1880 */
1881 /* assume a code label for branch instructions! */
1882 if( IS_ANY_BRANCH( CodeInfo->token ) )
1883 return( process_branch( CodeInfo, CurrOpnd, opndx ) );
1884
1885 switch( CodeInfo->token ) {
1886 case T_PUSH:
1887 case T_PUSHW:
1888 case T_PUSHD:
1889 /* v2.0: don't assume immediate operand if cpu is 8086 */
1890 if ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) > P_86 ) {
1891 //return( idata_nofixup( CodeInfo, opndx ) ); /* v1.96: changed */
1892 return( idata_fixup( CodeInfo, CurrOpnd, opndx ) );
1893 }
1894 break;
1895 default:
1896 /* v2.04: if operand is the second argument (and the first is NOT
1897 * a segment register!), scan the
1898 * instruction table if the instruction allows an immediate!
1899 * If so, assume the undefined symbol is a constant.
1900 */
1901 if ( CurrOpnd == OPND2 && (( CodeInfo->opnd[OPND1].type & OP_SR ) == 0 ) ) {
1902 const struct instr_item *p = CodeInfo->pinstr;
1903 do {
1904 if ( opnd_clstab[p->opclsidx].opnd_type[OPND2] & OP_I ) {
1905 return( idata_fixup( CodeInfo, CurrOpnd, opndx ) );
1906 }
1907 p++;
1908 } while ( p->first == FALSE );
1909 }
1910 /* v2.10: if current operand is the third argument, always assume an immediate */
1911 if ( CurrOpnd == OPND3 )
1912 return( idata_fixup( CodeInfo, CurrOpnd, opndx ) );
1913 }
1914 /* do default processing */
1915
1916 } else if( ( opndx->sym->state == SYM_SEG ) ||
1917 ( opndx->sym->state == SYM_GRP ) ) {
1918 DebugMsg1(("process_address: sym->state=SEG/GROUP\n"));
1919 /* SEGMENT and GROUP symbol is converted to SEG symbol
1920 * for next processing */
1921 opndx->instr = T_SEG;
1922 return( idata_fixup( CodeInfo, CurrOpnd, opndx ) );
1923 } else {
1924 DebugMsg1(("process_address direct, sym=%s sym.memtype=%X opndx.memtype=%X\n", opndx->sym->name, opndx->sym->mem_type, opndx->mem_type ));
1925
1926 /* symbol external, but absolute? */
1927 if( opndx->is_abs ) {
1928 return( idata_fixup( CodeInfo, CurrOpnd, opndx ) );
1929 }
1930
1931 /* CODE location is converted to OFFSET symbol */
1932 if ( opndx->mem_type == MT_NEAR || opndx->mem_type == MT_FAR ) {
1933 if( CodeInfo->token == T_LEA ) {
1934 return( memory_operand( CodeInfo, CurrOpnd, opndx, TRUE ) );
1935 //} else if( opndx->sym == &symPC ) {
1936 // return( idata_fixup( CodeInfo, opndx ) );
1937 } else if( opndx->mbr != NULL ) { /* structure field? */
1938 return( memory_operand( CodeInfo, CurrOpnd, opndx, TRUE ) );
1939 } else {
1940 return( idata_fixup( CodeInfo, CurrOpnd, opndx ) );
1941 }
1942 }
1943 }
1944 /* default processing: memory with fixup */
1945 return( memory_operand( CodeInfo, CurrOpnd, opndx, TRUE ) );
1946 }
1947
1948 /* Handle constant operands.
1949 * These never need a fixup. Externals - even "absolute" ones -
1950 * are always labeled as EXPR_ADDR by the expression evaluator.
1951 */
process_const(struct code_info * CodeInfo,unsigned CurrOpnd,struct expr * opndx)1952 static ret_code process_const( struct code_info *CodeInfo, unsigned CurrOpnd, struct expr *opndx )
1953 /************************************************************************************************/
1954 {
1955 #if 0 /* v2.06: obsolete */
1956 /* hack for IMUL: compress the operands so there are 2 only */
1957 if( ( CodeInfo->token == T_IMUL ) &&
1958 ( CodeInfo->opnd_type[OPND1] & OP_R ) ) {
1959 if( CurrOpnd == OPND2 ) {
1960 #if AMD64_SUPPORT
1961 CodeInfo->prefix.rex |= ((CodeInfo->prefix.rex & REX_B) ? REX_R : 0);
1962 #endif
1963 CodeInfo->rm_byte = ( CodeInfo->rm_byte & ~BIT_345 )
1964 | ( ( CodeInfo->rm_byte & BIT_012 ) << 3 );
1965 } else if( CurrOpnd == OPND3 ) {
1966 /* v2.04b: if op2 was assumed an immediate due to fwd ref,
1967 * change it back to a mem ref now.
1968 */
1969 if ( ( CodeInfo->opnd_type[OPND2] & OP_I ) &&
1970 CodeInfo->InsFixup[OPND2] &&
1971 CodeInfo->InsFixup[OPND2]->sym->state == SYM_UNDEFINED )
1972 CodeInfo->opnd_type[OPND2] = OP_M;
1973 CodeInfo->opnd_type[OPND1] = CodeInfo->opnd_type[OPND2];
1974 CodeInfo->opnd_type[OPND2] = OP_NONE;
1975 CodeInfo->data[OPND1] = CodeInfo->data[OPND2];
1976 CodeInfo->data[OPND2] = 0;
1977 CodeInfo->InsFixup[OPND1] = CodeInfo->InsFixup[OPND2];
1978 CodeInfo->InsFixup[OPND2] = NULL;
1979 CurrOpnd = OPND2;
1980 }
1981 }
1982 #endif
1983 /* v2.11: don't accept an empty string */
1984 if ( opndx->quoted_string && opndx->quoted_string->stringlen == 0 )
1985 return( EmitError( EMPTY_STRING ) );
1986
1987 /* optimization: skip <value> if it is 0 and instruction
1988 * is RET[W|D|N|F]. */
1989 /* v2.06: moved here and checked the opcode directly, so
1990 * RETD and RETW are also handled. */
1991 if ( ( ( CodeInfo->pinstr->opcode & 0xf7 ) == 0xc2 ) &&
1992 CurrOpnd == OPND1 && opndx->value == 0 ) {
1993 // (CodeInfo.token == T_RET ||
1994 // CodeInfo.token == T_RETN ||
1995 // CodeInfo.token == T_RETF)) {
1996 //if ( opndx.sym == NULL || opndx.sym->state == SYM_INTERNAL ) {
1997 return( NOT_ERROR );
1998 }
1999 return( idata_nofixup( CodeInfo, CurrOpnd, opndx ) );
2000 }
2001
process_register(struct code_info * CodeInfo,unsigned CurrOpnd,const struct expr opndx[])2002 static ret_code process_register( struct code_info *CodeInfo, unsigned CurrOpnd, const struct expr opndx[] )
2003 /**********************************************************************************************************/
2004 /*
2005 * parse and encode direct register operands. Modifies:
2006 * - CodeInfo->opnd_type
2007 * - CodeInfo->rm_byte (depending on CurrOpnd)
2008 * - CodeInfo->iswide
2009 * - CodeInfo->x86hi_used/x64lo_used
2010 * - CodeInfo->prefix.rex
2011 */
2012 {
2013 enum special_token regtok;
2014 int regno;
2015 uint_32 flags;
2016
2017 DebugMsg1(( "process_register enter (%s)\n", opndx[CurrOpnd].base_reg->string_ptr ));
2018 regtok = opndx[CurrOpnd].base_reg->tokval;
2019 regno = GetRegNo( regtok );
2020 /* the register's "OP-flags" are stored in the 'value' field */
2021 flags = GetValueSp( regtok );
2022 CodeInfo->opnd[CurrOpnd].type = flags;
2023 if ( flags & OP_R8 ) {
2024 /* it's probably better to not reset the wide bit at all */
2025 if ( flags != OP_CL ) /* problem: SHL AX|AL, CL */
2026 CodeInfo->iswide = 0;
2027
2028 #if AMD64_SUPPORT
2029 if ( CodeInfo->Ofssize == USE64 && regno >=4 && regno <=7 )
2030 if ( SpecialTable[regtok].cpu == P_86 )
2031 CodeInfo->x86hi_used = 1; /* it's AH,BH,CH,DH */
2032 else
2033 CodeInfo->x64lo_used = 1; /* it's SPL,BPL,SIL,DIL */
2034 #endif
2035 if ( StdAssumeTable[regno].error & (( regtok >= T_AH && regtok <= T_BH ) ? RH_ERROR : RL_ERROR ) ) {
2036 DebugMsg(("process_register: assume error, reg=%u\n", regno ));
2037 return( EmitError( USE_OF_REGISTER_ASSUMED_TO_ERROR ) );
2038 }
2039 } else if ( flags & OP_R ) { /* 16-, 32- or 64-bit GPR? */
2040 CodeInfo->iswide = 1;
2041 if ( StdAssumeTable[regno].error & flags & OP_R ) {
2042 DebugMsg(("process_register: assume error, reg=%u\n", regno ));
2043 return( EmitError( USE_OF_REGISTER_ASSUMED_TO_ERROR ) );
2044 }
2045 if ( flags & OP_R16 ) {
2046 if ( CodeInfo->Ofssize > USE16 )
2047 CodeInfo->prefix.opsiz = TRUE;
2048 } else {
2049 if( CodeInfo->Ofssize == USE16 )
2050 CodeInfo->prefix.opsiz = TRUE;
2051 }
2052 } else if ( flags & OP_SR ) {
2053 if( regno == 1 ) { /* 1 is CS */
2054 /* POP CS is not allowed */
2055 if( CodeInfo->token == T_POP ) {
2056 return( EmitError( POP_CS_IS_NOT_ALLOWED ) );
2057 }
2058 }
2059 } else if ( flags & OP_ST ) {
2060
2061 regno = opndx[CurrOpnd].st_idx;
2062 if ( regno > 7 ) { /* v1.96: index check added */
2063 return( EmitError( INVALID_COPROCESSOR_REGISTER ) );
2064 }
2065 CodeInfo->rm_byte |= regno;
2066 if( regno != 0 )
2067 CodeInfo->opnd[CurrOpnd].type = OP_ST_REG;
2068 /* v2.06: exit, rm_byte is already set. */
2069 return( NOT_ERROR );
2070
2071 } else if ( flags & OP_RSPEC ) { /* CRx, DRx, TRx */
2072 if( CodeInfo->token != T_MOV ) {
2073 return( EmitError( ONLY_MOV_CAN_USE_SPECIAL_REGISTER ) );
2074 }
2075 /* v2.04: previously there were 3 flags, OP_CR, OP_DR and OP_TR.
2076 * this was summoned to one flag OP_RSPEC to free 2 flags, which
2077 * are needed if AVC ( new YMM registers ) is to be supported.
2078 * To distinguish between CR, DR and TR, the register number is
2079 * used now: CRx are numbers 0-F, DRx are numbers 0x10-0x1F and
2080 * TRx are 0x20-0x2F.
2081 */
2082 if ( regno >= 0x20 ) { /* TRx? */
2083 CodeInfo->opc_or |= 0x04;
2084 /* TR3-TR5 are available on 486-586
2085 * TR6+TR7 are available on 386-586
2086 * v2.11: simplified.
2087 */
2088 if( ( ModuleInfo.curr_cpu & P_CPU_MASK ) >= P_686 ) {
2089 return( EmitErr( CANNOT_USE_TRN_TO_TRM_WITH_CURRENT_CPU_SETTING, regno > 0x25 ? 6 : 3, regno > 0x25 ? 7 : 5 ) );
2090 }
2091 } else if ( regno >= 0x10 ) { /* DRx? */
2092 CodeInfo->opc_or |= 0x01;
2093 }
2094 regno &= 0x0F;
2095 }
2096
2097 #if AMD64_SUPPORT
2098 /* if it's a x86-64 register (SIL, R8W, R8D, RSI, ... */
2099 if ( ( SpecialTable[regtok].cpu & P_CPU_MASK ) == P_64 ) {
2100 CodeInfo->prefix.rex |= 0x40;
2101 if ( flags & OP_R64 )
2102 CodeInfo->prefix.rex |= REX_W;
2103 }
2104 #endif
2105
2106 if( CurrOpnd == OPND1 ) {
2107 /* the first operand
2108 * r/m is treated as a 'reg' field */
2109 CodeInfo->rm_byte |= MOD_11;
2110 #if AMD64_SUPPORT
2111 CodeInfo->prefix.rex |= (regno & 8 ) >> 3; /* set REX_B */
2112 regno &= BIT_012;
2113 #endif
2114 /* fill the r/m field */
2115 CodeInfo->rm_byte |= regno;
2116 } else {
2117 /* the second operand
2118 * XCHG can use short form if op1 is AX/EAX/RAX */
2119 if( ( CodeInfo->token == T_XCHG ) && ( CodeInfo->opnd[OPND1].type & OP_A ) &&
2120 ( 0 == (CodeInfo->opnd[OPND1].type & OP_R8 ) ) ) {
2121 #if AMD64_SUPPORT
2122 CodeInfo->prefix.rex |= (regno & 8 ) >> 3; /* set REX_B */
2123 regno &= BIT_012;
2124 #endif
2125 CodeInfo->rm_byte = ( CodeInfo->rm_byte & BIT_67 ) | regno;
2126 } else {
2127 /* fill reg field with reg */
2128 #if AMD64_SUPPORT
2129 CodeInfo->prefix.rex |= (regno & 8 ) >> 1; /* set REX_R */
2130 regno &= BIT_012;
2131 #endif
2132 CodeInfo->rm_byte = ( CodeInfo->rm_byte & ~BIT_345 ) | ( regno << 3 );
2133 }
2134 }
2135 return( NOT_ERROR );
2136 }
2137
2138 /* v2.14: check if variable is accessible thru ES */
2139
IsAccessible(struct asym * sym,enum assume_segreg sr)2140 static bool IsAccessible( struct asym *sym, enum assume_segreg sr )
2141 /*****************************************************************/
2142 {
2143 if ( sym->segment && SegAssumeTable[sr].symbol )
2144 if ( sym->segment != SegAssumeTable[sr].symbol && GetGroup( sym ) != SegAssumeTable[sr].symbol )
2145 return( FALSE );
2146 return( TRUE );
2147 }
2148
2149 /* special handling for string instructions
2150 * CMPS[B|W|D|Q]
2151 * INS[B|W|D]
2152 * LODS[B|W|D|Q]
2153 * MOVS[B|W|D|Q]
2154 * OUTS[B|W|D]
2155 * SCAS[B|W|D|Q]
2156 * STOS[B|W|D|Q]
2157 * the peculiarity is that these instructions ( optionally )
2158 * have memory operands, which aren't used for code generation
2159 * <opndx> contains the last operand.
2160 */
2161
HandleStringInstructions(struct code_info * CodeInfo,const struct expr opndx[])2162 static void HandleStringInstructions( struct code_info *CodeInfo, const struct expr opndx[] )
2163 /*******************************************************************************************/
2164 {
2165 int opndidx = OPND1;
2166 int op_size;
2167
2168 /* v2.14: added quite a few checks. It works, but the source needs some cleanup now. */
2169
2170 switch( CodeInfo->token ) {
2171 #if AVXSUPP
2172 case T_VCMPSD:
2173 #endif
2174 case T_CMPSD:
2175 /* filter SSE2 opcode CMPSD */
2176 if ( CodeInfo->opnd[OPND1].type & (OP_XMM | OP_MMX)) {
2177 /* v2.01: QWORD operand for CMPSD/MOVSD may have set REX_W! */
2178 #if AMD64_SUPPORT
2179 CodeInfo->prefix.rex &= ~REX_W;
2180 #endif
2181 return;
2182 }
2183 /* fall through */
2184 case T_CMPS:
2185 case T_CMPSB:
2186 case T_CMPSW:
2187 #if AMD64_SUPPORT
2188 case T_CMPSQ:
2189 #endif
2190 /* v2.14: reject segment != ES for second op if symbolic */
2191 if ( CodeInfo->opnd[OPND2].type != OP_NONE && opndx[OPND2].override == NULL && opndx[OPND2].sym ) {
2192 if (!IsAccessible( opndx[OPND2].sym, ASSUME_ES )) {
2193 EmitError( INVALID_INSTRUCTION_OPERANDS );
2194 break;
2195 }
2196 }
2197 /* cmps allows prefix for the first operand (=source) only */
2198 if ( CodeInfo->prefix.RegOverride != ASSUME_NOTHING ) {
2199 if ( opndx[OPND2].override != NULL ) {
2200 if ( CodeInfo->prefix.RegOverride == ASSUME_ES ) {
2201 /* content of LastRegOverride is valid if
2202 * CodeInfo->RegOverride is != EMPTY.
2203 */
2204 if ( LastRegOverride == ASSUME_DS )
2205 CodeInfo->prefix.RegOverride = ASSUME_NOTHING;/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
2206 else
2207 CodeInfo->prefix.RegOverride = LastRegOverride;
2208 } else {
2209 DebugMsg1(("HandleStringInstructions: CMPS: CodeInfo->RegOverride=%X, opndx->override=%s\n", CodeInfo->prefix.RegOverride, opndx[OPND2].override->string_ptr ));
2210 EmitError( INVALID_INSTRUCTION_OPERANDS );
2211 }
2212 }
2213 } else if ( CodeInfo->opnd[OPND1].type != OP_NONE && /* v2.14 */
2214 opndx[OPND1].override == NULL &&
2215 opndx[OPND1].sym ) {
2216 check_assume( CodeInfo, opndx[OPND1].sym, ASSUME_DS );
2217 }
2218 if ( CodeInfo->prefix.RegOverride == ASSUME_DS ) {
2219 CodeInfo->prefix.RegOverride = ASSUME_NOTHING;/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
2220 }
2221 break;
2222 #if AVXSUPP
2223 case T_VMOVSD:
2224 #endif
2225 case T_MOVSD:
2226 /* filter SSE2 opcode MOVSD */
2227 if ( ( CodeInfo->opnd[OPND1].type & (OP_XMM | OP_MMX) ) ||
2228 ( CodeInfo->opnd[OPND2].type & (OP_XMM | OP_MMX) ) ) {
2229 /* v2.01: QWORD operand for CMPSD/MOVSD may have set REX_W! */
2230 #if AMD64_SUPPORT
2231 CodeInfo->prefix.rex &= ~REX_W;
2232 #endif
2233 return;
2234 }
2235 /* fall through */
2236 case T_MOVS:
2237 case T_MOVSB:
2238 case T_MOVSW:
2239 #if AMD64_SUPPORT
2240 case T_MOVSQ:
2241 #endif
2242 /* v2.14: reject segment != ES for first op if symbolic */
2243 if ( CodeInfo->opnd[OPND1].type != OP_NONE && opndx[OPND1].override == NULL && opndx[OPND1].sym ) {
2244 if (!IsAccessible( opndx[OPND1].sym, ASSUME_ES )) {
2245 EmitError( INVALID_INSTRUCTION_OPERANDS );
2246 break;
2247 }
2248 }
2249 /* MOVSx allows prefix for the second operand (=source) only.
2250 * there's only one place to store the register override in CodeInfo,
2251 * so it's a problem if both operands have an override; to be improved.
2252 */
2253 if ( CodeInfo->prefix.RegOverride != ASSUME_NOTHING ) {/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
2254 #if 1 /* v2.14: destination must be ES: */
2255 if ( opndx[OPND1].override && opndx[OPND1].override->token == T_REG && opndx[OPND1].override->tokval != T_ES ) {
2256 DebugMsg1(("HandleStringInstructions: MOVS: CodeInfo->RegOverride=%X, opndx->override=%s\n", CodeInfo->prefix.RegOverride, opndx[OPND1].override->string_ptr ));
2257 EmitError( INVALID_INSTRUCTION_OPERANDS );
2258 } else
2259 #endif
2260 if ( opndx[OPND2].override == NULL ) {
2261 /* v2.14: "if block" added */
2262 if ( CodeInfo->prefix.RegOverride == ASSUME_ES )
2263 CodeInfo->prefix.RegOverride = ASSUME_NOTHING;
2264 else {
2265 DebugMsg(("HandleStringInstructions: MOVS: override==NULL for second operand\n" ));
2266 EmitError( INVALID_INSTRUCTION_OPERANDS );
2267 }
2268 } //else if ( CodeInfo->prefix.RegOverride == ASSUME_DS )
2269 // CodeInfo->prefix.RegOverride = ASSUME_NOTHING;/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
2270 } else if ( CodeInfo->opnd[OPND2].type != OP_NONE && /* v2.14 */
2271 opndx[OPND2].override == NULL &&
2272 opndx[OPND2].sym ) {
2273 check_assume( CodeInfo, opndx[OPND2].sym, ASSUME_DS );
2274 }
2275 if ( CodeInfo->prefix.RegOverride == ASSUME_DS )
2276 CodeInfo->prefix.RegOverride = ASSUME_NOTHING;/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
2277 break;
2278 case T_OUTS:
2279 case T_OUTSB:
2280 case T_OUTSW:
2281 case T_OUTSD:
2282 /* v2.14 */
2283 if ( CodeInfo->opnd[OPND2].type != OP_NONE && opndx[OPND2].override == NULL && opndx[OPND2].sym )
2284 check_assume( CodeInfo, opndx[OPND2].sym, ASSUME_DS );
2285 /* v2.01: remove default DS prefix */
2286 if ( CodeInfo->prefix.RegOverride == ASSUME_DS )
2287 CodeInfo->prefix.RegOverride = ASSUME_NOTHING;/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
2288 opndidx = OPND2;
2289 break;
2290 case T_LODS:
2291 case T_LODSB:
2292 case T_LODSW:
2293 case T_LODSD:
2294 #if AMD64_SUPPORT
2295 case T_LODSQ:
2296 #endif
2297 /* v2.14 */
2298 if ( CodeInfo->opnd[OPND1].type != OP_NONE && opndx[OPND1].override == NULL && opndx[OPND1].sym )
2299 check_assume( CodeInfo, opndx[OPND1].sym, ASSUME_DS );
2300 /* v2.10: remove unnecessary DS prefix ( Masm-compatible ) */
2301 if ( CodeInfo->prefix.RegOverride == ASSUME_DS )
2302 CodeInfo->prefix.RegOverride = ASSUME_NOTHING;/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
2303 break;
2304 default: /*INS[B|W|D], SCAS[B|W|D|Q], STOS[B|W|D|Q] */
2305 /* INSx, SCASx and STOSx don't allow any segment prefix != ES
2306 for the memory operand.
2307 */
2308 /* v2.14: check added to reject invalid segment assumes */
2309 if ( CodeInfo->opnd[OPND1].type != OP_NONE && opndx[OPND1].override == NULL && opndx[OPND1].sym ) {
2310 DebugMsg1(("HandleStringInstructions: INS,SCAS,STOS: opndx->sym=%s\n", opndx[OPND1].sym->name ));
2311 if (!IsAccessible( opndx[OPND1].sym, ASSUME_ES )) {
2312 EmitError( INVALID_INSTRUCTION_OPERANDS );
2313 break;
2314 }
2315 }
2316 if ( CodeInfo->prefix.RegOverride != ASSUME_NOTHING )
2317 if ( CodeInfo->prefix.RegOverride == ASSUME_ES )
2318 CodeInfo->prefix.RegOverride = ASSUME_NOTHING;/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
2319 else
2320 EmitError( INVALID_INSTRUCTION_OPERANDS );
2321 }
2322
2323 if ( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[opndidx] == OP_NONE ) {
2324 CodeInfo->iswide = 0;
2325 CodeInfo->prefix.opsiz = FALSE;
2326 }
2327
2328 /* if the instruction is the variant without suffix (MOVS, LODS, ..),
2329 * then use the operand's size to get further info.
2330 */
2331 //if ( CodeInfo->pinstr->opnd_type[opndidx] != OP_NONE &&
2332 if ( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[opndidx] != OP_NONE &&
2333 CodeInfo->opnd[opndidx].type != OP_NONE ) {
2334 op_size = OperandSize( CodeInfo->opnd[opndidx].type, CodeInfo );
2335 /* v2.06: added. if memory operand has no size */
2336 if ( op_size == 0 ) {
2337 if ( CodeInfo->opnd[opndidx].InsFixup == NULL || CodeInfo->opnd[opndidx].InsFixup->sym->state != SYM_UNDEFINED )
2338 EmitError( INSTRUCTION_OPERAND_MUST_HAVE_SIZE );
2339 op_size = 1; /* assume shortest format */
2340 }
2341 switch( op_size ) {
2342 case 1:
2343 CodeInfo->iswide = 0;
2344 //if( CodeInfo->Ofssize )
2345 CodeInfo->prefix.opsiz = FALSE;
2346 break;
2347 case 2:
2348 CodeInfo->iswide = 1;
2349 CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? TRUE : FALSE;
2350 break;
2351 case 4:
2352 CodeInfo->iswide = 1;
2353 CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? FALSE : TRUE;
2354 break;
2355 #if AMD64_SUPPORT
2356 case 8:
2357 if ( CodeInfo->Ofssize == USE64 ) {
2358 CodeInfo->iswide = 1;
2359 CodeInfo->prefix.opsiz = FALSE;
2360 CodeInfo->prefix.rex = REX_W;
2361 }
2362 break;
2363 #endif
2364 }
2365 }
2366 return;
2367 }
2368
check_size(struct code_info * CodeInfo,const struct expr opndx[])2369 static ret_code check_size( struct code_info *CodeInfo, const struct expr opndx[] )
2370 /*********************************************************************************/
2371 /*
2372 * - use to make sure the size of first operand match the size of second operand;
2373 * - optimize MOV instruction;
2374 * - opndx contains last operand
2375 * todo: BOUND second operand check ( may be WORD/DWORD or DWORD/QWORD ).
2376 * tofix: add a flag in instr_table[] if there's NO check to be done.
2377 */
2378 {
2379 enum operand_type op1 = CodeInfo->opnd[OPND1].type;
2380 enum operand_type op2 = CodeInfo->opnd[OPND2].type;
2381 ret_code rc = NOT_ERROR;
2382 int op1_size;
2383 int op2_size;
2384 //int op_size = 0;
2385
2386 DebugMsg1(("check_size enter, optype1=%" I32_SPEC "X, optype2=%" I32_SPEC "X\n", op1, op2 ));
2387 switch( CodeInfo->token ) {
2388 case T_IN:
2389 if( op2 == OP_DX ) {
2390 /* wide and size is NOT determined by DX, but
2391 * by the first operand, AL|AX|EAX
2392 */
2393 switch( op1 ) {
2394 case OP_AX:
2395 break;
2396 case OP_AL:
2397 CodeInfo->iswide = 0; /* clear w-bit */
2398 case OP_EAX:
2399 if( CodeInfo->Ofssize ) {
2400 CodeInfo->prefix.opsiz = FALSE;
2401 }
2402 break;
2403 }
2404 }
2405 break;
2406 case T_OUT:
2407 if( op1 == OP_DX ) {
2408 switch( op2 ) {
2409 case OP_AX:
2410 break;
2411 case OP_AL:
2412 CodeInfo->iswide = 0; /* clear w-bit */
2413 case OP_EAX:
2414 if( CodeInfo->Ofssize ) {
2415 CodeInfo->prefix.opsiz = FALSE;
2416 }
2417 }
2418 }
2419 break;
2420 case T_LEA:
2421 #if 0
2422 /* first op must be 16/32 register, but this condition is checked
2423 in CodeGen. operands 1 and 2 can be mixed:
2424 lea cx,[bp]
2425 lea cx,[ebp]
2426 lea ecx,[bp]
2427 lea ecx,[ebp]
2428 are all valid. However, Masm sometimes complains
2429 "cannot use 16-bit register with a 32-bit address"
2430 */
2431 switch( OperandSize( op1, CodeInfo ) ) {
2432 case 2:
2433 case 4:
2434 break;
2435 default:
2436 EmitErr( OPERANDS_MUST_BE_THE_SAME_SIZE, OperandSize( op1, CodeInfo ), ModuleInfo.Ofssize ? 4 : 2);
2437 rc = ERROR;
2438 }
2439 #endif
2440 break;
2441 case T_RCL:
2442 case T_RCR:
2443 case T_ROL:
2444 case T_ROR:
2445 case T_SAL:
2446 case T_SAR:
2447 case T_SHL:
2448 case T_SHR:
2449 /* v2.11: added */
2450 if ( CodeInfo->opnd[OPND1].type == OP_M && CodeInfo->undef_sym == FALSE &&
2451 ( opndx[OPND1].sym == NULL || opndx[OPND1].sym->state != SYM_UNDEFINED ) ) {
2452 EmitErr( INSTRUCTION_OPERAND_MUST_HAVE_SIZE );
2453 rc = ERROR;
2454 break;
2455 }
2456 //if ( CodeInfo->opnd[OPND1].type == OP_M && Parse_Pass == PASS_2 )
2457 // EmitWarn( 2, SIZE_NOT_SPECIFIED_ASSUMING, "BYTE" );
2458
2459 /* v2.0: if second argument is a forward reference,
2460 * change type to "immediate 1"
2461 */
2462 if ( opndx[OPND2].kind == EXPR_ADDR &&
2463 Parse_Pass == PASS_1 &&
2464 opndx[OPND2].indirect == FALSE &&
2465 opndx[OPND2].sym &&
2466 opndx[OPND2].sym->state == SYM_UNDEFINED ) {
2467 CodeInfo->opnd[OPND2].type = OP_I8;
2468 CodeInfo->opnd[OPND2].data32l = 1;
2469 }
2470 /* v2.06: added (because if first operand is memory, wide bit
2471 * isn't set!)
2472 */
2473 if ( OperandSize( op1, CodeInfo ) > 1 )
2474 CodeInfo->iswide = 1;
2475 /* v2.06: makes the OP_CL_ONLY case in codegen.c obsolete */
2476 if ( op2 == OP_CL ) {
2477 /* CL is encoded in bit 345 of rm_byte, but we don't need it
2478 * so clear it here */
2479 CodeInfo->rm_byte &= NOT_BIT_345;
2480 }
2481 break;
2482 case T_LDS:
2483 case T_LES:
2484 case T_LFS:
2485 case T_LGS:
2486 case T_LSS:
2487 op1_size = OperandSize( op1, CodeInfo ) + 2; /* add 2 for the impl. segment register */
2488 op2_size = OperandSize( op2, CodeInfo );
2489 if ( op2_size != 0 && op1_size != op2_size ) {
2490 return( EmitError( INVALID_OPERAND_SIZE ) );
2491 }
2492 break;
2493 case T_ENTER:
2494 #if 0 /* v2.11: operand sizes are checked in codegen */
2495 /* ENTER has to be OP_I16, OP_I8_U */
2496 if( op1 == OP_I32 ) {
2497 /* parse_phase_1 will treat 16-bit data as OP_I32 if CPU is 386 */
2498 if( CodeInfo->opnd[OPND1].data32l > (int_32)USHRT_MAX ) {
2499 /* if op1 is really 32-bit data, then error */
2500 EmitError( INVALID_OPERAND_SIZE );
2501 rc = ERROR;
2502 }
2503 }
2504 /* type cast op1 to OP_I16 */
2505 CodeInfo->opnd[OPND1].type = OP_I16;
2506 /* op2 have to be 8-bit data */
2507 if( op2 >= OP_I16 ) {
2508 if( CodeInfo->opnd[OPND2].data32l > UCHAR_MAX ) {
2509 EmitError( INVALID_OPERAND_SIZE );
2510 rc = ERROR;
2511 }
2512 CodeInfo->opnd[OPND2].type = OP_I8;
2513 }
2514 #endif
2515 break;
2516 case T_MOVSX:
2517 case T_MOVZX:
2518 CodeInfo->iswide = 0;
2519 op1_size = OperandSize( op1, CodeInfo );
2520 op2_size = OperandSize( op2, CodeInfo );
2521 DebugMsg1(("check_size, MOVZX/MOVSX: op2_size=%u, opndx.memtype=%Xh, opndx.sym=%X\n", op2_size, opndx[OPND2].mem_type, opndx[OPND2].sym ));
2522 if ( op2_size == 0 && Parse_Pass == PASS_2 )
2523 if ( op1_size == 2 ) {
2524 EmitWarn( 2, SIZE_NOT_SPECIFIED_ASSUMING, "BYTE" );
2525 } else
2526 EmitErr( INSTRUCTION_OPERAND_MUST_HAVE_SIZE );
2527 switch( op1_size ) {
2528 #if AMD64_SUPPORT
2529 case 8:
2530 //if ( CodeInfo->Ofssize == USE64 )
2531 // break;
2532 #endif
2533 case 4:
2534 if (op2_size < 2)
2535 ;
2536 else if (op2_size == 2)
2537 CodeInfo->iswide = 1;
2538 else {
2539 EmitError( OP2_TOO_BIG );
2540 rc = ERROR;
2541 }
2542 CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? FALSE : TRUE;
2543 break;
2544 case 2:
2545 if( op2_size >= 2 ) {
2546 EmitError( OP2_TOO_BIG );
2547 rc = ERROR;
2548 }
2549 CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? TRUE : FALSE;
2550 break;
2551 default:
2552 /* op1 must be r16/r32/r64 */
2553 EmitError( OP1_TOO_SMALL );
2554 rc = ERROR;
2555 }
2556 break;
2557 #if AMD64_SUPPORT
2558 case T_MOVSXD:
2559 break;
2560 #endif
2561 case T_ARPL: /* v2.06: new, avoids the OP_R16 hack in codegen.c */
2562 CodeInfo->prefix.opsiz = 0;
2563 goto def_check;
2564 break;
2565 #if AMD64_SUPPORT
2566 case T_LAR: /* v2.04: added */
2567 case T_LSL: /* 19-sep-93 */
2568 #if 1 /* v2.04: changed */
2569 if ( ModuleInfo.Ofssize != USE64 || ( ( op2 & OP_M ) == 0 ) )
2570 goto def_check;
2571 /* in 64-bit, if second argument is memory operand,
2572 * ensure it has size WORD ( or 0 if a forward ref )
2573 */
2574 op2_size = OperandSize( op2, CodeInfo );
2575 if ( op2_size != 2 && op2_size != 0 ) {
2576 return( EmitError( INVALID_OPERAND_SIZE ) );
2577 }
2578 /* the opsize prefix depends on the FIRST operand only! */
2579 op1_size = OperandSize( op1, CodeInfo );
2580 if ( op1_size != 2 )
2581 CodeInfo->prefix.opsiz = FALSE;
2582 #else
2583 op1_size = OperandSize( op1, CodeInfo );
2584 switch( op1_size ) {
2585 case 2:
2586 if( CodeInfo->Ofssize )
2587 CodeInfo->prefix.opsiz = TRUE;
2588 break;
2589 case 4:
2590 if( CodeInfo->Ofssize )
2591 CodeInfo->prefix.opsiz = FALSE;
2592 break;
2593 default:
2594 return( EmitError( INVALID_OPERAND_SIZE ) );
2595 }
2596 op2_size = OperandSize( op2, CodeInfo );
2597 switch( op2_size ) {
2598 case 2:
2599 case 4:
2600 break;
2601 default:
2602 EmitError( INVALID_OPERAND_SIZE );
2603 rc = ERROR;
2604 break;
2605 }
2606 #endif
2607 break;
2608 #endif
2609 case T_IMUL: /* v2.06: check for 3rd operand must be done here */
2610 if ( CodeInfo->opnd[OPND3].type != OP_NONE ) {
2611 int op3_size;
2612 op1_size = OperandSize( op1, CodeInfo );
2613 op3_size = OperandSize( CodeInfo->opnd[OPND3].type, CodeInfo );
2614 /* the only case which must be checked here
2615 * is a WORD register as op1 and a DWORD immediate as op3 */
2616 if ( op1_size == 2 && op3_size > 2 ) {
2617 EmitErr( OPERANDS_MUST_BE_THE_SAME_SIZE, op1_size, op3_size );
2618 rc = ERROR;
2619 break;
2620 }
2621 if ( CodeInfo->opnd[OPND3].type & ( OP_I16 | OP_I32 ) )
2622 CodeInfo->opnd[OPND3].type = ( op1_size == 2 ? OP_I16 : OP_I32 );
2623 }
2624 goto def_check;
2625 break;
2626 case T_CVTSD2SI:
2627 case T_CVTTSD2SI:
2628 case T_CVTSS2SI:
2629 case T_CVTTSS2SI:
2630 //case T_MOVNTI: /* v2.05: removed */
2631 #if AVXSUPP
2632 case T_VBROADCASTSD:
2633 case T_VBROADCASTF128:
2634 case T_VEXTRACTF128:
2635 case T_VINSERTF128:
2636 case T_VCVTSD2SI:
2637 case T_VCVTTSD2SI:
2638 case T_VCVTSS2SI:
2639 case T_VCVTTSS2SI:
2640 #endif
2641 #if VMXSUPP /* v2.09: added */
2642 case T_INVEPT:
2643 case T_INVVPID:
2644 #endif
2645 #if SVMSUPP /* v2.09: added */
2646 case T_INVLPGA:
2647 #endif
2648 break;
2649 #if AVXSUPP
2650 case T_VCVTPD2DQ:
2651 case T_VCVTTPD2DQ:
2652 case T_VCVTPD2PS:
2653 if ( op2 == OP_M && opndx[OPND2].indirect ) {
2654 return( EmitError( INSTRUCTION_OPERAND_MUST_HAVE_SIZE ) );
2655 }
2656 break;
2657 case T_VMOVDDUP:
2658 if ( !( op1 & OP_YMM ) )
2659 break;
2660 /* fall through */
2661 case T_VPERM2F128: /* has just one memory variant, and VX_L isnt set */
2662 if ( op2 == OP_M )
2663 CodeInfo->opnd[OPND2].type |= OP_M256;
2664 break;
2665 #endif
2666 #if SSE4SUPP
2667 case T_CRC32:
2668 /* v2.02: for CRC32, the second operand determines whether an
2669 * OPSIZE prefix byte is to be written.
2670 */
2671 op2_size = OperandSize( op2, CodeInfo );
2672 if ( op2_size < 2)
2673 CodeInfo->prefix.opsiz = FALSE;
2674 else if ( op2_size == 2 )
2675 CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? TRUE : FALSE;
2676 else
2677 CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? FALSE : TRUE;
2678 break;
2679 #endif
2680 case T_MOVD:
2681 #if 0
2682 op1_size = OperandSize( op1, CodeInfo );
2683 op2_size = OperandSize( op2, CodeInfo );
2684 if( ( op1_size != 0 ) && ( op1_size != 4 )
2685 || ( op2_size != 0 ) && ( op2_size != 4 ) ) {
2686 EmitErr( OPERANDS_MUST_BE_THE_SAME_SIZE, op1_size, op2_size );
2687 rc = ERROR;
2688 }
2689 #endif
2690 break;
2691 case T_MOV:
2692 if( op1 & OP_SR ) { /* segment register as op1? */
2693 op2_size = OperandSize( op2, CodeInfo );
2694 if( ( op2_size == 2 ) || ( op2_size == 4 )
2695 #if AMD64_SUPPORT
2696 || ( op2_size == 8 && ModuleInfo.Ofssize == USE64 )
2697 #endif
2698 ) {
2699 return( NOT_ERROR );
2700 }
2701 } else if( op2 & OP_SR ) {
2702 op1_size = OperandSize( op1, CodeInfo );
2703 if( ( op1_size == 2 ) || ( op1_size == 4 )
2704 #if AMD64_SUPPORT
2705 || ( op1_size == 8 && ModuleInfo.Ofssize == USE64 )
2706 #endif
2707 ) {
2708 return( NOT_ERROR );
2709 }
2710 } else if( ( op1 & OP_M ) && ( op2 & OP_A ) ) { /* 1. operand memory reference, 2. AL|AX|EAX|RAX? */
2711
2712 if ( CodeInfo->isdirect == FALSE ) {
2713 /* address mode is indirect.
2714 * don't use the short format (opcodes A0-A3) - it exists for direct
2715 * addressing only. Reset OP_A flag!
2716 */
2717 CodeInfo->opnd[OPND2].type &= ~OP_A;
2718 DebugMsg1(("check_size: OP_A flag reset, new op2=%X\n", CodeInfo->opnd[OPND2].type ));
2719 #if AMD64_SUPPORT
2720 } else if ( CodeInfo->Ofssize == USE64 && ( CodeInfo->opnd[OPND1].data64 < 0x80000000 || CodeInfo->opnd[OPND1].data64 >= 0xffffffff80000000 ) ) {
2721 /* for 64bit, opcodes A0-A3 ( direct memory addressing with AL/AX/EAX/RAX )
2722 * are followed by a full 64-bit moffs. This is only used if the offset won't fit
2723 * in a 32-bit signed value.
2724 */
2725 CodeInfo->opnd[OPND2].type &= ~OP_A;
2726 DebugMsg1(("check_size: OP_A flag reset, new op2=%X\n", CodeInfo->opnd[OPND2].type ));
2727 #endif
2728 }
2729
2730 } else if( ( op1 & OP_A ) && ( op2 & OP_M ) ) { /* 2. operand memory reference, 1. AL|AX|EAX|RAX? */
2731
2732 if ( CodeInfo->isdirect == FALSE ) {
2733 CodeInfo->opnd[OPND1].type &= ~OP_A;
2734 DebugMsg1(("check_size: OP_A flag reset, new op1=%X\n", CodeInfo->opnd[OPND1].type ));
2735 #if AMD64_SUPPORT
2736 } else if ( CodeInfo->Ofssize == USE64 && ( CodeInfo->opnd[OPND2].data64 < 0x80000000 || CodeInfo->opnd[OPND2].data64 >= 0xffffffff80000000 ) ) {
2737 CodeInfo->opnd[OPND1].type &= ~OP_A;
2738 DebugMsg1(("check_size: OP_A flag reset, new op2=%X\n", CodeInfo->opnd[OPND1].type ));
2739 #endif
2740 }
2741 }
2742 /* fall through */
2743 default:
2744 //#if AMD64_SUPPORT
2745 def_check:
2746 //#endif
2747 /* make sure the 2 opnds are of the same type */
2748 op1_size = OperandSize( op1, CodeInfo );
2749 op2_size = OperandSize( op2, CodeInfo );
2750 DebugMsg1(("check_size default: op1_size1=%u, op2_size=%u\n", op1_size, op2_size));
2751 if( op1_size > op2_size ) {
2752 if( ( op2 >= OP_I8 ) && ( op2 <= OP_I32 ) ) { /* immediate */
2753 op2_size = op1_size; /* promote to larger size */
2754 }
2755 }
2756 #if 1
2757 /* v2.04: check in idata_nofixup was signed,
2758 * so now add -256 - -129 and 128-255 to acceptable byte range.
2759 * Since Masm v8, the check is more restrictive, -255 - -129
2760 * is no longer accepted.
2761 */
2762 if( ( op1_size == 1 ) && ( op2 == OP_I16 ) &&
2763 ( CodeInfo->opnd[OPND2].data32l <= UCHAR_MAX ) &&
2764 //CodeInfo->opnd[OPND2].data32l >= -128 ) ) {
2765 ( CodeInfo->opnd[OPND2].data32l >= -255 ) ) {
2766 return( rc ); /* OK cause no sign extension */
2767 }
2768 #endif
2769 #if 0
2770 /* v2.03: this "if" made JWasm accept any 32-bit constant
2771 * for 16-bit destinations, which is Masm compatibel,
2772 * "mov ax, 12345h"
2773 * the test is a bit too liberal here, IMO, because
2774 * it makes JWasm accept "mov ax, near32 ptr var",
2775 * which is rejected by Masm.
2776 */
2777 if( ( op1_size == 2 ) && ( op2 == OP_I32 )
2778 && ( CodeInfo->data[OPND2] <= USHRT_MAX ) ) {
2779 return( rc ); /* OK cause no sign extension */
2780 }
2781 #endif
2782 if( op1_size != op2_size ) {
2783 /* if one or more are !defined, set them appropriately */
2784 #if AVXSUPP
2785 if( ( op1 | op2 ) & ( OP_MMX | OP_XMM | OP_YMM ) ) {
2786 #else
2787 if( ( op1 | op2 ) & ( OP_MMX | OP_XMM ) ) {
2788 #endif
2789 } else if( ( op1_size != 0 ) && ( op2_size != 0 ) ) {
2790 EmitErr( OPERANDS_MUST_BE_THE_SAME_SIZE, op1_size, op2_size );
2791 rc = ERROR;
2792 }
2793 /* size == 0 is assumed to mean "undefined", but there
2794 * is also the case of an "empty" struct or union. The
2795 * latter case isn't handled correctly.
2796 */
2797 if( op1_size == 0 ) {
2798 if( ( op1 & OP_M_ANY ) && ( op2 & OP_I ) ) {
2799 char *p = "WORD";
2800 if( (uint_32)CodeInfo->opnd[OPND2].data32l > USHRT_MAX || op2_size == 4 ) {
2801 CodeInfo->iswide = 1;
2802 DebugMsg1(("check_size: op1=%X op1_size=0, op2=%X, op2_size=%u CodeInfo->data[2]=%X\n", op1, op2, op2_size, CodeInfo->opnd[OPND2].data32l ));
2803 #if 1 /* added v1.95: in 16bit code, 'mov [di],8000h' should warn: assuming WORD */
2804 if ( ModuleInfo.Ofssize == USE16 && op2_size > 2 && InWordRange( CodeInfo->opnd[OPND2].data32l ) )
2805 op2_size = 2;
2806 #endif
2807 if (op2_size <= 2 && CodeInfo->opnd[OPND2].data32l > SHRT_MIN && ModuleInfo.Ofssize == USE16 ) {
2808 CodeInfo->mem_type = MT_WORD;
2809 CodeInfo->opnd[OPND2].type = OP_I16;
2810 } else {
2811 CodeInfo->mem_type = MT_DWORD;
2812 CodeInfo->opnd[OPND2].type = OP_I32;
2813 p = "DWORD";
2814 }
2815 } else if( (uint_32)CodeInfo->opnd[OPND2].data32l > UCHAR_MAX || op2_size == 2 ) {
2816 CodeInfo->mem_type = MT_WORD;
2817 CodeInfo->iswide = 1;
2818 CodeInfo->opnd[OPND2].type = OP_I16;
2819 } else {
2820 CodeInfo->mem_type = MT_BYTE;
2821 CodeInfo->opnd[OPND2].type = OP_I8;
2822 p = "BYTE";
2823 }
2824 if( opndx[OPND2].explicit == FALSE ) {
2825 /* v2.06: emit warning at pass one if mem op isn't a forward ref */
2826 /* v2.06b: added "undefined" check */
2827 if ( ( CodeInfo->opnd[OPND1].InsFixup == NULL && Parse_Pass == PASS_1 && CodeInfo->undef_sym == FALSE ) ||
2828 ( CodeInfo->opnd[OPND1].InsFixup && Parse_Pass == PASS_2 ) )
2829 EmitWarn( 1, SIZE_NOT_SPECIFIED_ASSUMING, p );
2830 }
2831 } else if( ( op1 & OP_M_ANY ) && ( op2 & ( OP_R | OP_SR ) ) ) {
2832 } else if( ( op1 & ( OP_MMX | OP_XMM ) ) && ( op2 & OP_I ) ) {
2833 if( (uint_32)CodeInfo->opnd[OPND2].data32l > USHRT_MAX ) {
2834 CodeInfo->opnd[OPND2].type = OP_I32;
2835 } else if( (uint_32)CodeInfo->opnd[OPND2].data32l > UCHAR_MAX ) {
2836 CodeInfo->opnd[OPND2].type = OP_I16;
2837 } else {
2838 CodeInfo->opnd[OPND2].type = OP_I8;
2839 }
2840 } else if( ( op1 | op2 ) & ( OP_MMX | OP_XMM ) ) {
2841 } else {
2842 //AsmIntErr( 1 ); /* printf("internal error = %u", 1 ) */
2843 switch( op2_size ) {
2844 case 1:
2845 CodeInfo->mem_type = MT_BYTE;
2846 if( ( Parse_Pass == PASS_1 ) && ( op2 & OP_I ) ) {
2847 EmitWarn( 1, SIZE_NOT_SPECIFIED_ASSUMING, "BYTE" );
2848 }
2849 break;
2850 case 2:
2851 CodeInfo->mem_type = MT_WORD;
2852 CodeInfo->iswide = 1;
2853 if( ( Parse_Pass == PASS_1 ) && ( op2 & OP_I ) ) {
2854 EmitWarn( 1, SIZE_NOT_SPECIFIED_ASSUMING, "WORD" );
2855 }
2856 if( CodeInfo->Ofssize )
2857 CodeInfo->prefix.opsiz = TRUE;
2858 break;
2859 case 4:
2860 CodeInfo->mem_type = MT_DWORD;
2861 CodeInfo->iswide = 1;
2862 if( ( Parse_Pass == PASS_1 ) && ( op2 & OP_I ) ) {
2863 EmitWarn( 1, SIZE_NOT_SPECIFIED_ASSUMING, "DWORD" );
2864 }
2865 break;
2866 }
2867 }
2868 }
2869 }
2870 }
2871 DebugMsg1(("check_size exit [CodeInfo->mem_type=%Xh]\n", CodeInfo->mem_type));
2872 return( rc );
2873 }
2874
2875 static struct asym *IsType( const char *name )
2876 /********************************************/
2877 {
2878 struct asym *sym;
2879
2880 sym = SymSearch( name );
2881 if ( sym && (sym->state == SYM_TYPE ) )
2882 return( sym );
2883 return( NULL );
2884 }
2885
2886 /*
2887 * ParseLine() is the main parser function.
2888 * It scans the tokens in tokenarray[] and does:
2889 * - for code labels: call CreateLabel()
2890 * - for data items and data directives: call data_dir()
2891 * - for other directives: call directive[]()
2892 * - for instructions: fill CodeInfo and call codegen()
2893 */
2894
2895 ret_code ParseLine( struct asm_tok tokenarray[] )
2896 /**********************************************/
2897 {
2898 int i;
2899 int j;
2900 unsigned dirflags;
2901 unsigned CurrOpnd;
2902 ret_code temp;
2903 struct asym *sym;
2904 uint_32 oldofs;
2905 #ifdef DEBUG_OUT
2906 char *instr;
2907 #endif
2908 struct code_info CodeInfo;
2909 #if AVXSUPP
2910 struct expr opndx[MAX_OPND+1];
2911 #else
2912 struct expr opndx[MAX_OPND];
2913 #endif
2914
2915 DebugMsg1(("ParseLine enter, Token_Count=%u, ofs=%Xh\n",
2916 Token_Count, GetCurrOffset() ));
2917
2918 i = 0;
2919
2920 /* Does line start with a code label? */
2921 if ( tokenarray[0].token == T_ID && ( tokenarray[1].token == T_COLON || tokenarray[1].token == T_DBL_COLON ) ) {
2922 i = 2;
2923 DebugMsg1(("ParseLine T_COLON, code label=%s\n", tokenarray[0].string_ptr ));
2924 if( ProcStatus & PRST_PROLOGUE_NOT_DONE ) write_prologue( tokenarray );
2925
2926 /* create a global or local code label */
2927 if( CreateLabel( tokenarray[0].string_ptr, MT_NEAR, NULL,
2928 ( ModuleInfo.scoped && CurrProc && tokenarray[1].token != T_DBL_COLON ) ) == NULL ) {
2929 DebugMsg(("ParseLine, CreateLabel(%s) failed, exit\n", tokenarray[0].string_ptr ));
2930 return( ERROR );
2931 }
2932 if ( tokenarray[i].token == T_FINAL ) {
2933 /* v2.06: this is a bit too late. Should be done BEFORE
2934 * CreateLabel, because of '@@'. There's a flag supposed to
2935 * be used for this handling, LOF_STORED in line_flags.
2936 * It's only a problem if a '@@:' is the first line
2937 * in the code section.
2938 * v2.10: is no longer an issue because the label counter has
2939 * been moved to module_vars (see global.h).
2940 */
2941 FStoreLine(0);
2942 if ( CurrFile[LST] ) {
2943 LstWrite( LSTTYPE_LABEL, 0, NULL );
2944 }
2945 return( NOT_ERROR );
2946 }
2947 }
2948
2949 /* handle directives and (anonymous) data items */
2950
2951 if ( tokenarray[i].token != T_INSTRUCTION ) {
2952 /* a code label before a data item is only accepted in Masm5 compat mode */
2953 Frame_Type = FRAME_NONE;
2954 SegOverride = NULL;
2955 if ( i == 0 && tokenarray[0].token == T_ID ) {
2956 /* token at pos 0 may be a label.
2957 * it IS a label if:
2958 * 1. token at pos 1 is a directive (lbl dd ...)
2959 * 2. token at pos 0 is NOT a userdef type ( lbl DWORD ...)
2960 * 3. inside a struct and token at pos 1 is a userdef type
2961 * or a predefined type. (usertype DWORD|usertype ... )
2962 * the separate namespace allows this syntax here.
2963 */
2964 if( tokenarray[1].token == T_DIRECTIVE )
2965 i++;
2966 else {
2967 sym = IsType( tokenarray[0].string_ptr );
2968 if ( sym == NULL )
2969 i++;
2970 else if ( CurrStruct &&
2971 ( ( tokenarray[1].token == T_STYPE ) ||
2972 ( tokenarray[1].token == T_ID && ( IsType( tokenarray[1].string_ptr ) ) ) ) )
2973 i++;
2974 }
2975 }
2976 switch ( tokenarray[i].token ) {
2977 case T_DIRECTIVE:
2978 DebugMsg1(("ParseLine: T_DIRECTIVE >%s<\n", tokenarray[i].string_ptr ));
2979 if ( tokenarray[i].dirtype == DRT_DATADIR ) {
2980 return( data_dir( i, tokenarray, NULL ) );
2981 }
2982 dirflags = GetValueSp( tokenarray[i].tokval );
2983 if( CurrStruct && ( dirflags & DF_NOSTRUC ) ) {
2984 return( EmitError( STATEMENT_NOT_ALLOWED_INSIDE_STRUCTURE_DEFINITION ) );
2985 }
2986 /* label allowed for directive? */
2987 //if ( tokenarray[i].flags & DF_LABEL ) {
2988 if ( dirflags & DF_LABEL ) {
2989 if ( i && tokenarray[0].token != T_ID ) {
2990 return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) );
2991 }
2992 } else if ( i && tokenarray[i-1].token != T_COLON && tokenarray[i-1].token != T_DBL_COLON ) {
2993 return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i-1].string_ptr ) );
2994 }
2995 /* must be done BEFORE FStoreLine()! */
2996 if( ( ProcStatus & PRST_PROLOGUE_NOT_DONE ) && ( dirflags & DF_PROC ) ) write_prologue( tokenarray );
2997 #if FASTPASS
2998 if ( StoreState || ( dirflags & DF_STORE ) ) {
2999 /* v2.07: the comment must be stored as well
3000 * if a listing (with -Sg) is to be written and
3001 * the directive will generate lines
3002 */
3003 if ( ( dirflags & DF_CGEN ) && ModuleInfo.CurrComment && ModuleInfo.list_generated_code ) {
3004 FStoreLine(1);
3005 } else
3006 FStoreLine(0);
3007 }
3008 #endif
3009 if ( tokenarray[i].dirtype > DRT_DATADIR ) {
3010 temp = directive_tab[tokenarray[i].dirtype]( i, tokenarray );
3011 } else {
3012 temp = ERROR;
3013 /* ENDM, EXITM and GOTO directives should never be seen here */
3014 switch( tokenarray[i].tokval ) {
3015 case T_ENDM:
3016 EmitError( UNMATCHED_MACRO_NESTING );
3017 break;
3018 case T_EXITM:
3019 case T_GOTO:
3020 EmitError( DIRECTIVE_MUST_APPEAR_INSIDE_A_MACRO );
3021 break;
3022 default:
3023 /* this error may happen if
3024 * CATSTR, SUBSTR, MACRO, ...
3025 * aren't at pos 1
3026 */
3027 EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
3028 break;
3029 }
3030 }
3031 /* v2.0: for generated code it's important that list file is
3032 * written in ALL passes, to update file position! */
3033 //if ( ModuleInfo.list && (( line_flags & LOF_LISTED ) == 0 ) && Parse_Pass == PASS_1 )
3034 #if FASTPASS
3035 /* v2.08: UseSavedState == FALSE added */
3036 if ( ModuleInfo.list && ( Parse_Pass == PASS_1 || ModuleInfo.GeneratedCode || UseSavedState == FALSE ) )
3037 #else
3038 if ( ModuleInfo.list )
3039 #endif
3040 LstWriteSrcLine();
3041 return( temp );
3042 case T_STYPE:
3043 DebugMsg1(("ParseLine: T_STYPE >%s<\n", tokenarray[i].string_ptr ));
3044 return( data_dir( i, tokenarray, NULL ) );
3045 case T_ID:
3046 DebugMsg1(("ParseLine: T_ID >%s<\n", tokenarray[i].string_ptr ));
3047 if( sym = IsType( tokenarray[i].string_ptr ) ) {
3048 return( data_dir( i, tokenarray, sym ) );
3049 }
3050 break;
3051 default:
3052 if ( tokenarray[i].token == T_COLON ) {
3053 DebugMsg(("ParseLine: unexpected colon\n" ));
3054 return( EmitError( SYNTAX_ERROR_UNEXPECTED_COLON ) );
3055 }
3056 break;
3057 } /* end switch (tokenarray[i].token) */
3058 if ( i && tokenarray[i-1].token == T_ID )
3059 i--;
3060 DebugMsg(("ParseLine: unexpected token=%u, i=%u, string=%s\n", tokenarray[i].token, i, tokenarray[i].string_ptr));
3061 return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
3062 }
3063
3064 DebugMsg1(("ParseLine: %s\n", tokenarray[i].string_ptr));
3065 /* v2.04 added */
3066 if( CurrStruct ) {
3067 return( EmitError( STATEMENT_NOT_ALLOWED_INSIDE_STRUCTURE_DEFINITION ) );
3068 }
3069
3070 if( ProcStatus & PRST_PROLOGUE_NOT_DONE ) write_prologue( tokenarray );
3071
3072 /* v2.07: moved because special handling is needed for RET/IRET */
3073 //FStoreLine(); /* must be placed AFTER write_prologue() */
3074
3075 if ( CurrFile[LST] ) oldofs = GetCurrOffset();
3076
3077 /* init CodeInfo */
3078 CodeInfo.prefix.ins = EMPTY;
3079 CodeInfo.prefix.RegOverride = ASSUME_NOTHING;/* v2.12: EMPTY -> ASSUME_NOTHING to avoid warning */
3080 #if AMD64_SUPPORT
3081 CodeInfo.prefix.rex = 0;
3082 #endif
3083 CodeInfo.prefix.adrsiz = FALSE;
3084 CodeInfo.prefix.opsiz = FALSE;
3085 CodeInfo.mem_type = MT_EMPTY;
3086 for( j = 0; j < MAX_OPND; j++ ) {
3087 CodeInfo.opnd[j].type = OP_NONE;
3088 #ifdef DEBUG_OUT
3089 CodeInfo.opnd[j].data32l = -1;
3090 /* make sure it's invalid */
3091 CodeInfo.opnd[j].InsFixup = (void *)0xffffffff;
3092 #endif
3093 }
3094 CodeInfo.rm_byte = 0;
3095 CodeInfo.sib = 0; /* assume ss is *1 */
3096 CodeInfo.Ofssize = ModuleInfo.Ofssize;
3097 CodeInfo.opc_or = 0;
3098 #if AVXSUPP
3099 CodeInfo.vexregop = 0;
3100 #endif
3101 CodeInfo.flags = 0;
3102
3103 /* instruction prefix?
3104 * T_LOCK, T_REP, T_REPE, T_REPNE, T_REPNZ, T_REPZ */
3105 if ( tokenarray[i].tokval >= T_LOCK && tokenarray[i].tokval <= T_REPZ ) {
3106 CodeInfo.prefix.ins = tokenarray[i].tokval;
3107 i++;
3108 /* prefix has to be followed by an instruction */
3109 if( tokenarray[i].token != T_INSTRUCTION ) {
3110 DebugMsg(("ParseLine: unexpected token %u after prefix, exit, error\n", tokenarray[i].token ));
3111 return( EmitError( PREFIX_MUST_BE_FOLLOWED_BY_AN_INSTRUCTION ) );
3112 }
3113 DebugMsg1(("ParseLine: %s\n", tokenarray[i].tokpos));
3114 };
3115
3116 if( CurrProc ) {
3117 switch( tokenarray[i].tokval ) {
3118 case T_RET:
3119 case T_IRET: /* IRET is always 16-bit; OTOH, IRETW doesn't exist */
3120 case T_IRETD:
3121 #if AMD64_SUPPORT
3122 case T_IRETQ:
3123 #endif
3124 if ( !( ProcStatus & PRST_INSIDE_EPILOGUE ) && ModuleInfo.epiloguemode != PEM_NONE ) {
3125 /* v2.07: special handling for RET/IRET */
3126 FStoreLine( ( ModuleInfo.CurrComment && ModuleInfo.list_generated_code ) ? 1 : 0 );
3127 ProcStatus |= PRST_INSIDE_EPILOGUE;
3128 temp = RetInstr( i, tokenarray, Token_Count );
3129 ProcStatus &= ~PRST_INSIDE_EPILOGUE;
3130 return( temp );
3131 }
3132 /* default translation: just RET to RETF if proc is far */
3133 /* v2.08: this code must run even if PRST_INSIDE_EPILOGUE is set */
3134 if ( tokenarray[i].tokval == T_RET && CurrProc->sym.mem_type == MT_FAR )
3135 tokenarray[i].tokval = T_RETF;
3136 }
3137 }
3138
3139 FStoreLine(0); /* must be placed AFTER write_prologue() */
3140
3141 #ifdef DEBUG_OUT
3142 instr = tokenarray[i].string_ptr;
3143 #endif
3144 CodeInfo.token = tokenarray[i].tokval;
3145 /* get the instruction's start position in InstrTable[] */
3146 CodeInfo.pinstr = &InstrTable[IndexFromToken( CodeInfo.token )];
3147 i++;
3148
3149 if( CurrSeg == NULL ) {
3150 return( EmitError( MUST_BE_IN_SEGMENT_BLOCK ) );
3151 }
3152 if( CurrSeg->e.seginfo->segtype == SEGTYPE_UNDEF ) {
3153 CurrSeg->e.seginfo->segtype = SEGTYPE_CODE;
3154 }
3155 if ( ModuleInfo.CommentDataInCode )
3156 omf_OutSelect( FALSE );
3157
3158 /* get the instruction's arguments.
3159 * This loop accepts up to 4 arguments if AVXSUPP is on */
3160
3161 for ( j = 0; j < sizeof(opndx)/sizeof(opndx[0]) && tokenarray[i].token != T_FINAL; j++ ) {
3162 if ( j ) {
3163 if ( tokenarray[i].token != T_COMMA )
3164 break;
3165 i++;
3166 }
3167 DebugMsg1(("ParseLine(%s): calling EvalOperand, i=%u\n", instr, i));
3168 if( EvalOperand( &i, tokenarray, Token_Count, &opndx[j], 0 ) == ERROR ) {
3169 DebugMsg(("ParseLine(%s): EvalOperand() failed\n", instr ));
3170 return( ERROR );
3171 }
3172 switch ( opndx[j].kind ) {
3173 case EXPR_FLOAT:
3174 /* v2.06: accept float constants for PUSH */
3175 if ( j == OPND2 || CodeInfo.token == T_PUSH || CodeInfo.token == T_PUSHD ) {
3176 #if FPIMMEDIATE
3177 if ( Options.strict_masm_compat == FALSE ) {
3178 /* convert to REAL4, unless REAL8 coercion is requested */
3179 atofloat( &opndx[j].fvalue, opndx[j].float_tok->string_ptr, opndx[j].mem_type == MT_REAL8 ? 8 : 4, opndx[j].negative, opndx[j].float_tok->floattype );
3180 opndx[j].kind = EXPR_CONST;
3181 opndx[j].float_tok = NULL;
3182 break;
3183 }
3184 #endif
3185 /* Masm message is: real or BCD number not allowed */
3186 return( EmitError( FP_INITIALIZER_IGNORED ) );
3187 }
3188 /* fall through */
3189 case EXPR_EMPTY:
3190 if ( i == Token_Count )
3191 i--; /* v2.08: if there was a terminating comma, display it */
3192 /* fall through */
3193 case EXPR_ERROR:
3194 DebugMsg(("ParseLine(%s): unexpected operand kind=%d, error, exit\n", instr, opndx[j].kind ));
3195 return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
3196 }
3197 }
3198 if ( tokenarray[i].token != T_FINAL ) {
3199 DebugMsg(("ParseLine(%s): too many operands (%s) \n", instr, tokenarray[i].tokpos ));
3200 return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ) );
3201 }
3202
3203 for ( CurrOpnd = 0; CurrOpnd < j && CurrOpnd < MAX_OPND; CurrOpnd++ ) {
3204
3205 Frame_Type = FRAME_NONE;
3206 SegOverride = NULL; /* segreg prefix is stored in RegOverride */
3207 CodeInfo.opnd[CurrOpnd].data32l = 0;
3208 CodeInfo.opnd[CurrOpnd].InsFixup = NULL;
3209
3210 #if AVXSUPP
3211 /* if encoding is VEX and destination op is XMM, YMM or memory,
3212 * the second argument may be stored in the vexregop field.
3213 */
3214 if ( CodeInfo.token >= VEX_START &&
3215 CurrOpnd == OPND2 &&
3216 ( CodeInfo.opnd[OPND1].type & ( OP_XMM | OP_YMM | OP_M | OP_M256 ) ) ) {
3217 if ( vex_flags[CodeInfo.token - VEX_START] & VX_NND )
3218 ;
3219 else if ( ( vex_flags[CodeInfo.token - VEX_START] & VX_IMM ) &&
3220 ( opndx[OPND3].kind == EXPR_CONST ) && ( j > 2 ) )
3221 ;
3222 else if ( ( vex_flags[CodeInfo.token - VEX_START] & VX_NMEM ) &&
3223 ( ( CodeInfo.opnd[OPND1].type & OP_M ) ||
3224 /* v2.11: VMOVSD and VMOVSS always have 2 ops if a memory op is involved */
3225 ( ( CodeInfo.token == T_VMOVSD || CodeInfo.token == T_VMOVSS ) && ( opndx[OPND2].kind != EXPR_REG || opndx[OPND2].indirect == TRUE ) ) )
3226 )
3227 ;
3228 else {
3229 if ( opndx[OPND2].kind != EXPR_REG ||
3230 ( ! ( GetValueSp( opndx[CurrOpnd].base_reg->tokval ) & ( OP_XMM | OP_YMM ) ) ) ) {
3231 DebugMsg(("ParseLine(%s,%u): avx invalid operand, op2.kind=%u\n", instr, CurrOpnd, opndx[OPND2].kind ));
3232 return( EmitErr( INVALID_INSTRUCTION_OPERANDS ) );
3233 }
3234 /* fixme: check if there's an operand behind OPND2 at all!
3235 * if no, there's no point to continue with switch (opndx[].kind).
3236 * v2.11: additional check for j <= 2 added
3237 */
3238 if ( j <= 2 ) {
3239 DebugMsg(("ParseLine(%s,%u): avx not enough operands (%u)\n", instr, CurrOpnd, opndx[OPND2].kind, j ));
3240 /* v2.11: next line should be activated - currently the error is emitted below as syntax error */
3241 //return( EmitErr( INVALID_INSTRUCTION_OPERANDS ) );
3242 } else
3243 /* flag VX_DST is set if an immediate is expected as operand 3 */
3244 if ( ( vex_flags[CodeInfo.token - VEX_START] & VX_DST ) &&
3245 ( opndx[OPND3].kind == EXPR_CONST ) ) {
3246 DebugMsg1(("ParseLine(%s,%u): avx VX_DST, op3.kind=CONST (value=%u), numops=%u\n", instr, CurrOpnd, opndx[OPND3].kind, opndx[OPND3].value, j ));
3247 if ( opndx[OPND1].base_reg ) {
3248 /* first operand register is moved to vexregop */
3249 /* handle VEX.NDD */
3250 CodeInfo.vexregop = opndx[OPND1].base_reg->bytval + 1;
3251 memcpy( &opndx[OPND1], &opndx[CurrOpnd], sizeof( opndx[0] ) * 3 );
3252 CodeInfo.rm_byte = 0;
3253 if ( process_register( &CodeInfo, OPND1, opndx ) == ERROR )
3254 return( ERROR );
3255 }
3256 } else {
3257 unsigned flags = GetValueSp( opndx[CurrOpnd].base_reg->tokval );
3258 DebugMsg1(("ParseLine(%s,%u): opnd2 is avx reg (%s), flags=%X ci.type[0]=%X numops=%u\n",
3259 instr, CurrOpnd, opndx[CurrOpnd].base_reg->string_ptr, flags, CodeInfo.opnd[OPND1].type, j ));
3260 #if 1
3261 /* v2.08: no error here if first op is an untyped memory reference
3262 * note that OP_M includes OP_M128, but not OP_M256 (to be fixed?)
3263 */
3264 if ( CodeInfo.opnd[OPND1].type == OP_M )
3265 ; else
3266 #endif
3267 if ( ( flags & ( OP_XMM | OP_M128 ) ) &&
3268 ( CodeInfo.opnd[OPND1].type & (OP_YMM | OP_M256 ) ) ||
3269 ( flags & ( OP_YMM | OP_M256 ) ) &&
3270 ( CodeInfo.opnd[OPND1].type & (OP_XMM | OP_M128 ) ) ) {
3271 DebugMsg(("ParseLine(%s,%u): avx invalid opnd 2, flags=%X ci.type[0]=%X\n", instr, CurrOpnd, flags, CodeInfo.opnd[OPND1].type ));
3272 return( EmitErr( INVALID_INSTRUCTION_OPERANDS ) );
3273 }
3274 /* second operand register is moved to vexregop */
3275 /* to be fixed: CurrOpnd is always OPND2, so use this const here */
3276 CodeInfo.vexregop = opndx[CurrOpnd].base_reg->bytval + 1;
3277 memcpy( &opndx[CurrOpnd], &opndx[CurrOpnd+1], sizeof( opndx[0] ) * 2 );
3278 }
3279 j--;
3280 }
3281 }
3282 #endif
3283 DebugMsg1(("ParseLine(%s,%u): type/value/mem_type/ofssize=%Xh/%" I64_SPEC "Xh/%Xh/%d\n", instr, CurrOpnd, opndx[CurrOpnd].kind, opndx[CurrOpnd].value64, opndx[CurrOpnd].mem_type, opndx[CurrOpnd].Ofssize ));
3284 switch( opndx[CurrOpnd].kind ) {
3285 case EXPR_ADDR:
3286 DebugMsg1(("ParseLine(%s,%u): type ADDRESS\n", instr, CurrOpnd ));
3287 if ( process_address( &CodeInfo, CurrOpnd, &opndx[CurrOpnd] ) == ERROR )
3288 return( ERROR );
3289 break;
3290 case EXPR_CONST:
3291 DebugMsg1(("ParseLine(%s,%u): type CONST, opndx.memtype=%Xh\n", instr, CurrOpnd, opndx[CurrOpnd].mem_type));
3292 if ( process_const( &CodeInfo, CurrOpnd, &opndx[CurrOpnd] ) == ERROR )
3293 return( ERROR );
3294 break;
3295 case EXPR_REG:
3296 DebugMsg1(("ParseLine(%s,%u): type REG\n", instr, CurrOpnd ));
3297 if( opndx[CurrOpnd].indirect ) { /* indirect operand ( "[EBX+...]" )? */
3298 if ( process_address( &CodeInfo, CurrOpnd, &opndx[CurrOpnd] ) == ERROR )
3299 return( ERROR );
3300 } else {
3301 /* process_register() can't handle 3rd operand */
3302 if ( CurrOpnd == OPND3 ) {
3303 CodeInfo.opnd[OPND3].type = GetValueSp( opndx[CurrOpnd].base_reg->tokval );
3304 CodeInfo.opnd[OPND3].data32l = opndx[CurrOpnd].base_reg->bytval;
3305 } else if ( process_register( &CodeInfo, CurrOpnd, opndx ) == ERROR )
3306 return( ERROR );
3307 }
3308 break;
3309 }
3310 } /* end for */
3311 #if AVXSUPP
3312 /* 4 arguments are valid vor AVX only */
3313 if ( CurrOpnd != j ) {
3314 for ( ; tokenarray[i].token != T_COMMA; i-- )
3315 ;/* v2.12: semicolon on a separate line to avoid warning */
3316 DebugMsg(("ParseLine(%s): CurrOpnd != j ( %u - %u ) >%s<\n", instr, CurrOpnd, j, tokenarray[i].tokpos ));
3317 return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ) );
3318 }
3319 #endif
3320
3321 /* for FAR calls/jmps some special handling is required:
3322 * in the instruction tables, the "far" entries are located BEHIND
3323 * the "near" entries, that's why it's needed to skip all items
3324 * until the next "first" item is found.
3325 */
3326 if ( CodeInfo.isfar ) {
3327 if ( CodeInfo.token == T_CALL || CodeInfo.token == T_JMP ) {
3328 do {
3329 CodeInfo.pinstr++;
3330 } while ( CodeInfo.pinstr->first == FALSE );
3331 }
3332 }
3333 /* special handling for string instructions */
3334
3335 if ( CodeInfo.pinstr->allowed_prefix == AP_REP ||
3336 CodeInfo.pinstr->allowed_prefix == AP_REPxx ) {
3337 HandleStringInstructions( &CodeInfo, opndx );
3338 #if SVMSUPP /* v2.09, not active because a bit too hackish yet - it "works", though. */
3339 } else if ( CodeInfo.token >= T_VMRUN && CodeInfo.token <= T_INVLPGA && CodeInfo.pinstr->opclsidx ) {
3340 /* the size of the first operand is to trigger the address size byte 67h,
3341 * not the operand size byte 66h!
3342 */
3343 CodeInfo.prefix.adrsiz = CodeInfo.prefix.opsiz;
3344 CodeInfo.prefix.opsiz = 0;
3345 /* the first op must be EAX/AX or RAX/EAX. The operand class
3346 * used in the instruction table is OP_A ( which is AL/AX/EAX/RAX ).
3347 */
3348 if ( ( CodeInfo.opnd[OPND1].type & ( CodeInfo.Ofssize == USE64 ? OP_R64 | OP_R32 : OP_R32 | OP_R16 ) ) == 0 ) {
3349 DebugMsg(("ParseLine(%s): opnd1 unexpected type=%X\n", instr, CodeInfo.opnd[OPND1].type ));
3350 return( EmitErr( INVALID_INSTRUCTION_OPERANDS ) );
3351 }
3352 /* the INVLPGA instruction has a fix second operand (=ECX). However, there's no
3353 * operand class for ECX alone. So it has to be ensured here that the register IS ecx.
3354 */
3355 if ( CodeInfo.token == T_INVLPGA )
3356 if ( ( CodeInfo.rm_byte & BIT_345 ) != ( 1 << 3 ) ) { /* ECX is register 1 */
3357 DebugMsg(("ParseLine(%s): opnd2 is not ecx\n", instr ));
3358 return( EmitErr( INVALID_INSTRUCTION_OPERANDS ) );
3359 }
3360 #endif
3361 } else {
3362 if( CurrOpnd > 1 ) {
3363 /* v1.96: check if a third argument is ok */
3364 if ( CurrOpnd > 2 ) {
3365 do {
3366 //if ( CodeInfo.pinstr->opnd_type_3rd != OP3_NONE )
3367 if ( opnd_clstab[CodeInfo.pinstr->opclsidx].opnd_type_3rd != OP3_NONE )
3368 break;
3369 CodeInfo.pinstr++;
3370 if ( CodeInfo.pinstr->first == TRUE ) {
3371 DebugMsg(("ParseLine(%s): no third operand expected\n", instr ));
3372 for ( ; tokenarray[i].token != T_COMMA; i-- );
3373 return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ) );
3374 }
3375 } while ( 1 );
3376 }
3377 /* v2.06: moved here from process_const() */
3378 if ( CodeInfo.token == T_IMUL ) {
3379 /* the 2-operand form with an immediate as second op
3380 * is actually a 3-operand form. That's why the rm byte
3381 * has to be adjusted. */
3382 if ( CodeInfo.opnd[OPND3].type == OP_NONE && ( CodeInfo.opnd[OPND2].type & OP_I ) ) {
3383 #if AMD64_SUPPORT
3384 CodeInfo.prefix.rex |= ((CodeInfo.prefix.rex & REX_B) ? REX_R : 0 );
3385 #endif
3386 CodeInfo.rm_byte = ( CodeInfo.rm_byte & ~BIT_345 ) | ( ( CodeInfo.rm_byte & BIT_012 ) << 3 );
3387 } else if ( ( CodeInfo.opnd[OPND3].type != OP_NONE ) &&
3388 ( CodeInfo.opnd[OPND2].type & OP_I ) &&
3389 CodeInfo.opnd[OPND2].InsFixup &&
3390 CodeInfo.opnd[OPND2].InsFixup->sym->state == SYM_UNDEFINED )
3391 CodeInfo.opnd[OPND2].type = OP_M;
3392 }
3393 if( check_size( &CodeInfo, opndx ) == ERROR ) {
3394 DebugMsg(("ParseLine(%s): check_size() failed, exit\n", instr ));
3395 return( ERROR );
3396 }
3397 }
3398 #if AMD64_SUPPORT
3399 if ( CodeInfo.Ofssize == USE64 ) {
3400
3401 //if ( CodeInfo.x86hi_used && ( CodeInfo.x64lo_used || CodeInfo.prefix.rex & 7 ))
3402 if ( CodeInfo.x86hi_used && CodeInfo.prefix.rex )
3403 EmitError( INVALID_USAGE_OF_AHBHCHDH );
3404
3405 /* for some instructions, the "wide" flag has to be removed selectively.
3406 * this is to be improved - by a new flag in struct instr_item.
3407 */
3408 switch ( CodeInfo.token ) {
3409 case T_PUSH:
3410 case T_POP:
3411 /* v2.06: REX.W prefix is always 0, because size is either 2 or 8 */
3412 //if ( CodeInfo.opnd_type[OPND1] & OP_R64 )
3413 CodeInfo.prefix.rex &= 0x7;
3414 break;
3415 case T_CALL:
3416 case T_JMP:
3417 #if VMXSUPP /* v2.09: added */
3418 case T_VMREAD:
3419 case T_VMWRITE:
3420 #endif
3421 /* v2.02: previously rex-prefix was cleared entirely,
3422 * but bits 0-2 are needed to make "call rax" and "call r8"
3423 * distinguishable!
3424 */
3425 //CodeInfo.prefix.rex = 0;
3426 CodeInfo.prefix.rex &= 0x7;
3427 break;
3428 case T_MOV:
3429 /* don't use the Wide bit for moves to/from special regs */
3430 if ( CodeInfo.opnd[OPND1].type & OP_RSPEC || CodeInfo.opnd[OPND2].type & OP_RSPEC )
3431 CodeInfo.prefix.rex &= 0x7;
3432 break;
3433 }
3434 }
3435 #endif
3436 }
3437
3438 /* now call the code generator */
3439
3440 return( codegen( &CodeInfo, oldofs ) );
3441 }
3442
3443 /* process a file. introduced in v2.11 */
3444
3445 void ProcessFile( struct asm_tok tokenarray[] )
3446 /*********************************************/
3447 {
3448 while ( ModuleInfo.EndDirFound == FALSE && GetTextLine( CurrSource ) ) {
3449 if ( PreprocessLine( CurrSource, tokenarray ) ) {
3450 ParseLine( tokenarray );
3451 if ( Options.preprocessor_stdout == TRUE && Parse_Pass == PASS_1 )
3452 WritePreprocessedLine( CurrSource );
3453 }
3454 }
3455 return;
3456 }
3457
3458