1 /****************************************************************************
2 *
3 *  This code is Public Domain.
4 *
5 *  ========================================================================
6 *
7 * Description:  reserved word handling, including hash table access
8 *
9 ****************************************************************************/
10 
11 #include "globals.h"
12 #include "memalloc.h"
13 #include "parser.h"
14 #include "reswords.h"
15 #include "expreval.h"
16 #include "condasm.h"
17 #include "codegen.h"
18 #ifdef __I86__
19 #include "i86.h"
20 #endif
21 
22 //#define HASH_TABITEMS 211
23 #if AVXSUPP
24 #define HASH_TABITEMS 811
25 #else
26 #define HASH_TABITEMS 599
27 #endif
28 
29 #if 0 // def __I86__
30 /* optionally, for JWASMR, use a void based pointer for the name field.
31  * However, this requires to deactivate the RENAMEKEYWORD option!
32  */
33 #define GetPtr( x, y ) seg:>x->y
34 #define BASEPTR
35 #else
36 #define GetPtr( x, y ) x->y
37 #endif
38 
39 /* reserved words hash table */
40 static uint_16 resw_table[ HASH_TABITEMS ];
41 
42 /* define unary operand (LOW, HIGH, OFFSET, ...) type flags */
43 enum unary_operand_types {
44 #define res( value, func ) UOT_ ## value,
45 #include "unaryop.h"
46 #undef res
47 };
48 
49 /* v2.06: the following operand combinations are used
50  * inside InstrTable[] only, they don't need to be known
51  * by the parser.
52  */
53 enum operand_sets {
54     OP_R_MS      = ( OP_R | OP_MS ),
55     OP_R8_M08    = ( OP_R8 | OP_M08 ),
56     OP_RGT8_MS   = ( OP_RGT8 | OP_MS ),
57     OP_RGT8_MGT8 = ( OP_RGT8 | OP_MGT8 ),
58     OP_RMGT16    = ( OP_RGT16 | OP_MGT16 ),
59     OP_RGT16_M08 = ( OP_RGT16 | OP_M08 ),
60     OP_R16_R32   = ( OP_R16 | OP_R32 ),
61     OP_R16_M16   = ( OP_R16 | OP_M16 ),
62     OP_R32_M08   = ( OP_R32 | OP_M08 ),
63     OP_R32_M16   = ( OP_R32 | OP_M16 ),
64     OP_R32_M32   = ( OP_R32 | OP_M32 ),
65 #if AMD64_SUPPORT
66     OP_R16_R64   = ( OP_R16 | OP_R64 ),
67     OP_R64_M64   = ( OP_R64 | OP_M64 ),
68     OP_M16_M64   = ( OP_M16 | OP_M64 ),
69 #endif
70     OP_M16_M32   = ( OP_M16 | OP_M32 ),
71     OP_MMX_M64   = ( OP_MMX | OP_M64 ),
72     OP_XMM_M16   = ( OP_XMM | OP_M16 ),
73     OP_XMM_M32   = ( OP_XMM | OP_M32 ),
74     OP_XMM_M64   = ( OP_XMM | OP_M64 ),
75     OP_XMM_M128  = ( OP_XMM | OP_M128 ),
76 #if MASM_SSE_MEMX
77 /* extended Masm syntax: sometimes Masm accepts 2 mem types
78  * for the memory operand, although the mem access will always
79  * be QWORD/OWORD.
80  */
81     OP_MMX_M64_08  = ( OP_MMX | OP_M64  | OP_M08 ),
82     OP_MMX_M64_16  = ( OP_MMX | OP_M64  | OP_M16 ),
83     OP_MMX_M64_32  = ( OP_MMX | OP_M64  | OP_M32 ),
84 
85     OP_XMM_M128_08 = ( OP_XMM | OP_M128 | OP_M08 ),
86     OP_XMM_M128_16 = ( OP_XMM | OP_M128 | OP_M16 ),
87     OP_XMM_M128_32 = ( OP_XMM | OP_M128 | OP_M32 ),
88     OP_XMM_M128_64 = ( OP_XMM | OP_M128 | OP_M64 ),
89 #else
90 /* see macro OpCls() below */
91 #define OPC_MMXMMX_M64_08NONE  OPC_MMXMMX_M64NONE
92 #define OPC_MMXMMX_M64_16NONE  OPC_MMXMMX_M64NONE
93 #define OPC_MMXMMX_M64_32NONE  OPC_MMXMMX_M64NONE
94 
95 #define OPC_XMMXMM_M128_08NONE OPC_XMMXMM_M128NONE
96 #define OPC_XMMXMM_M128_16NONE OPC_XMMXMM_M128NONE
97 #define OPC_XMMXMM_M128_32NONE OPC_XMMXMM_M128NONE
98 #define OPC_XMMXMM_M128_64NONE OPC_XMMXMM_M128NONE
99 #endif
100 #if AVXSUPP
101     OP_YMM_M256  = ( OP_YMM | OP_M256 ),
102 #endif
103 };
104 
105 /* v2.06: operand types have been removed from InstrTable[], they
106  * are stored now in their own table, opnd_clstab[], below.
107  * This will allow to add a 4th operand ( AVX ) more effectively.
108  */
109 enum opnd_variants {
110 #define OpCls( op1, op2, op3 ) OPC_ ## op1 ## op2 ## op3,
111 #include "opndcls.h"
112 #undef OpCls
113 };
114 
115 /* the tables to handle "reserved words" are now generated:
116  * 1. InstrTable: contains info for instructions.
117  *    instructions may need multiple rows!
118  * 2. SpecialTable: contains info for reserved words which are
119  *    NOT instructions. One row each.
120  * 3. optable_idx: array of indices for InstrTable.
121  * 4. resw_strings: strings of reserved words. No terminating x'00'!
122  * 5. ResWordTable: array of reserved words (name, name length, flags).
123  *
124  * Each reserved word has a "token" value assigned, which is a short integer.
125  * This integer can be used as index for:
126  * - SpecialTable
127  * - optable_idx ( needs adjustment, better use macro IndexFromToken() )
128  * - ResWordTable
129  */
130 
131 /* create InstrTable. */
132 
133 #define OpCls( op1, op2, op3 ) OPC_ ## op1 ## op2 ## op3
134 
135 const struct instr_item InstrTable[] = {
136 #define ins(tok, string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
137     { opcls, byte1_info, prefix, 1, rm_info, op_dir, 0, cpu, opcode, rm_byte },
138 #define insx(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix,flgs) \
139     { opcls, byte1_info, prefix, 1, rm_info, op_dir, 0, cpu, opcode, rm_byte },
140 #define insn(tok,suffix,     opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
141     { opcls, byte1_info, prefix, 0, rm_info, op_dir, 0, cpu, opcode, rm_byte },
142 #define insm(tok,suffix,     opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
143     { opcls, byte1_info, prefix, 1, rm_info, op_dir, 0, cpu, opcode, rm_byte },
144 #include "instruct.h"
145 #include "instr64.h"
146 ins (NULL,0,OpCls(NONE,NONE,NONE),0,0,0,0,0,0,0) /* last entry - needed for its ".first" (=1) field */
147 #undef insm
148 #undef insn
149 #undef insx
150 #undef ins
151 };
152 #undef OpCls
153 
154 /* create SpecialTable. */
155 
156 const struct special_item SpecialTable[] = {
157     { 0, 0, 0, 0, 0 }, /* dummy entry for T_NULL */
158 #define res(tok, string, type, value, bytval, flags, cpu, sflags ) \
159     { value, sflags, cpu, bytval, type },
160 #include "special.h"
161 #undef res
162 #define res(tok, string, value, bytval, flags, cpu, sflags ) \
163     { value, sflags, cpu, bytval, RWT_DIRECTIVE },
164 #include "directve.h"
165 #undef res
166 };
167 
168 /* define symbolic indices for InstrTable[] */
169 
170 enum res_idx {
171 #define  ins(tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _I,
172 #define insx(tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix,flgs) T_ ## tok ## _I,
173 #define insn(tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _ ## suffix,
174 #define insm(tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _ ## suffix,
175 #include "instruct.h"
176 #undef insm
177 #undef insn
178 #undef ins
179 
180 #define  ins(tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _I64,
181 #define insn(tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _ ## suffix ## _I64,
182 #define insm(tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _ ## suffix ## _I64,
183 #include "instr64.h"
184 #undef insm
185 #undef insn
186 #undef insx
187 #undef ins
188 //T_NULL_I /* v2.06: removed */
189 };
190 
191 /* create optable_idx, the index array for InstrTable.
192  * This is needed because instructions often need more than
193  * one entry in InstrTable.
194  */
195 
196 uint_16 optable_idx[] = {
197 
198 #define  ins( tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _I,
199 #define insx( tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix,flgs) T_ ## tok ## _I,
200 #define insn( tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix)
201 #define insm( tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix)
202 #include "instruct.h"
203 #undef insm
204 #undef insn
205 #undef insx
206 #undef ins
207 
208     /* v2.06: this was superfluous, because the additional entries for
209      * 64-bit are only needed in InstrTable[]. For optable_idx[], a
210      * patch is done (see patchtabr[])
211      */
212 //#define  ins(tok,string, op1,op2,op3, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) T_ ## tok ## _I64,
213 //#define insn(tok,suffix, op1,op2,op3, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) T_ ## tok ## _ ## suffix ## _I64,
214 //#define insm(tok,suffix, op1,op2,op3, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) T_ ## tok ## _ ## suffix ## _I64,
215 //#include "instr64.h"
216 //#undef insm
217 //#undef insn
218 //#undef ins
219 
220 #if AVXSUPP
221 #define avxins( tok, string, cpu, flgs ) T_ ## tok ## _I,
222 #include "instravx.h"
223 #undef avxins
224 #endif
225     //T_NULL_I /* v2.06: also not needed */
226 };
227 
228 /* table of instruction operand classes
229  */
230 const struct opnd_class opnd_clstab[] = {
231 #define OpCls( op1, op2, op3 ) { { OP_ ## op1, OP_ ## op2 }, OP3_ ## op3 },
232 #include "opndcls.h"
233 #undef OpCls
234 };
235 
236 /* create the strings for all reserved words */
237 
238 static const char resw_strings[] = {
239 #define res(tok, string, type, value, bytval, flags, cpu, sflags) \
240  # string
241 #include "special.h"
242 #undef res
243 #define res(tok, string, value, bytval, flags, cpu, sflags) \
244  # string
245 #include "directve.h"
246 #undef res
247 
248 #define ins(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
249  # string
250 #define insn(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix)
251 #define insm(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix)
252 #define insx(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix,flgs) \
253  # string
254 #include "instruct.h"
255 #if AVXSUPP
256 #define avxins( tok, string, cpu, flgs ) # string
257 #include "instravx.h"
258 #undef avxins
259 #endif
260     "syscall_" /* replacement for "syscall" language type in 64-bit */
261 };
262 #define strSyscall_ &resw_strings[sizeof(resw_strings)-9]
263 #undef insx
264 #undef insm
265 #undef insn
266 #undef ins
267 
268 /* create the 'reserved words' table (ResWordTable).
269  * this table's entries will be used to create the instruction hash table.
270  * v2.11: RWF_SPECIAL flag removed:
271  * { 0, sizeof(#string)-1, RWF_SPECIAL | flags, NULL },
272  */
273 struct ReservedWord ResWordTable[] = {
274     { 0, 0, 0, NULL }, /* dummy entry for T_NULL */
275 #define res(tok, string, type, value, bytval, flags, cpu, sflags) \
276     { 0, sizeof(#string)-1, flags, NULL },
277 #include "special.h"
278 #undef res
279 #define res(tok, string, value, bytval, flags, cpu, sflags) \
280     { 0, sizeof(#string)-1, flags, NULL },
281 #include "directve.h"
282 #undef res
283 
284 #define ins(tok,string,  opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
285     { 0, sizeof(#string)-1, 0, NULL },
286 #define insn(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix)
287 #define insm(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix)
288 #define insx(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix,flags) \
289     { 0, sizeof(#string)-1, flags, NULL },
290 #include "instruct.h"
291 #undef insx
292 #undef insm
293 #undef insn
294 #undef ins
295 #if AVXSUPP
296 #define avxins( tok, string, cpu, flgs ) \
297     { 0, sizeof(#string)-1, RWF_VEX, NULL },
298 #include "instravx.h"
299 #undef avxins
300 #endif
301 };
302 
303 #if AVXSUPP
304 /* these is a special 1-byte array for vex-encoded instructions.
305  * it could probably be moved to InstrTable[] (there is an unused byte),
306  * but in fact it's the wrong place, since the content of vex_flags[]
307  * are associated with opcodes, not with instruction variants.
308  */
309 const uint_8 vex_flags[] = {
310     /* flags for the AVX instructions in instruct.h. The order must
311      * be equal to the one in instruct.h! ( this is to be improved.)
312      * For a description of the VX_ flags see codegen.h
313      */
314     VX_NND,      /* VBROADCASTSS   */
315     VX_NND,      /* VBROADCASTSD   */
316     VX_NND,      /* VBROADCASTF128 */
317     VX_L,        /* VBLENDVPD      */
318     VX_L,        /* VBLENDVPS      */
319     0,           /* VINSERTF128    */
320     VX_NND,      /* VEXTRACTF128   */
321     VX_L,        /* VMASKMOVPS     */
322     VX_L,        /* VMASKMOVPD     */
323     0,           /* VPBLENDVB      */
324     VX_L|VX_IMM, /* VPERMILPD      */
325     VX_L|VX_IMM, /* VPERMILPS      */
326     /* VPERMIL2xx has been dropped */
327     //VX_L,      /* VPERMIL2PD     */
328     //VX_L,      /* VPERMIL2PS     */
329     0,           /* VPERM2F128     */
330     VX_L|VX_NND, /* VTESTPS        */
331     VX_L|VX_NND, /* VTESTPD        */
332     VX_L,        /* VZEROALL       */
333     0,           /* VZEROUPPER     */
334     VX_NND,      /* VCVTPD2DQ      */
335     VX_NND,      /* VCVTTPD2DQ     */
336     VX_NND,      /* VCVTPD2PS      */
337     VX_NND,      /* VMOVDDUP       */
338     VX_L|VX_NND, /* VMOVMSKPD      */ /* v2.11 */
339     VX_L|VX_NND, /* VMOVMSKPS      */ /* v2.11 */
340 #define avxins( tok, string, cpu, flgs ) flgs,
341 #include "instravx.h"
342 #undef avxins
343 };
344 #endif
345 
346 #if AMD64_SUPPORT
347 
348 /* keywords to be added for 64-bit */
349 static const enum instr_token patchtab64[] = {
350     T_SPL,             /* add x64 register part of special.h */
351     T_FRAME,           /* add x64 reserved word part of special.h */
352     T_DOT_ALLOCSTACK,  /* add x64 directive part of directve.h (win64) */
353     T_JRCXZ,           /* branch instructions must be grouped together */
354     T_CDQE,            /* add x64 part of instruct.h */
355 #if AVXSUPP
356     T_VPEXTRQ,         /* add x64 part of instravx.h */
357 #endif
358 };
359 
360 /* keywords to be removed for 64-bit */
361 static const enum instr_token patchtab32[] = {
362     T_TR3,          /* registers invalid for IA32+              */
363     T_DOT_SAFESEH,  /* directives invalid for IA32+             */
364     T_AAA,          /* instructions invalid for IA32+           */
365     T_JCXZ,         /* 1. branch instructions invalid for IA32+ */
366     T_LOOPW         /* 2. branch instructions invalid for IA32+ */
367 };
368 
369 struct replace_ins {
370     uint_16       tok; /* is an optable_idx[] index */
371     enum res_idx  idx32;
372     enum res_idx  idx64;
373 };
374 
375 /* keyword entries to be changed for 64-bit (see instr64.h) */
376 static const struct replace_ins patchtabr[] = {
377     { T_LGDT - SPECIAL_LAST, T_LGDT_I, T_LGDT_I64 },
378     { T_LIDT - SPECIAL_LAST, T_LIDT_I, T_LIDT_I64 },
379     { T_CALL - SPECIAL_LAST, T_CALL_I, T_CALL_I64 },
380     { T_JMP  - SPECIAL_LAST, T_JMP_I,  T_JMP_I64  },
381     { T_POP  - SPECIAL_LAST, T_POP_I,  T_POP_I64  }, /* v2.06: added */
382     { T_PUSH - SPECIAL_LAST, T_PUSH_I, T_PUSH_I64 }, /* v2.06: added */
383 #if 1
384     /* with Masm, in 16/32-bit SLDT|SMSW|STR accept a WORD argument only -
385      * in 64-bit (ML64), 32- and 64-bit registers are also accepted!
386      */
387     { T_SLDT - SPECIAL_LAST, T_SLDT_I, T_SLDT_I64 },
388     { T_SMSW - SPECIAL_LAST, T_SMSW_I, T_SMSW_I64 },
389     { T_STR  - SPECIAL_LAST, T_STR_I,  T_STR_I64  },
390 #endif
391 #if VMXSUPP /* v2.09: added */
392     { T_VMREAD  - SPECIAL_LAST, T_VMREAD_I,   T_VMREAD_I64  },
393     { T_VMWRITE - SPECIAL_LAST, T_VMWRITE_I,  T_VMWRITE_I64 },
394 #endif
395 };
396 
397 #endif
398 
399 #if RENAMEKEY
400 static struct qdesc renamed_keys = { NULL, NULL };
401 #endif
402 
403 /* global queue of "disabled" reserved words.
404  * just indices of ResWordTable[] are used.
405  */
406 static struct {
407     uint_16 Head;
408     uint_16 Tail;
409 } Removed = { 0, 0 };
410 
411 #if AMD64_SUPPORT
412 static bool  b64bit = FALSE; /* resw tables in 64bit mode? */
413 #endif
414 
get_hash(const char * s,unsigned char size)415 static unsigned get_hash( const char *s, unsigned char size )
416 /***********************************************************/
417 {
418     uint_32 h;
419     uint_32 g;
420 
421     for( h = 0; size; size-- ) {
422         /* ( h & ~0x0fff ) == 0 is always true here */
423         h = (h << 3) + (*s++ | ' ');
424         g = h & ~0x1fff;
425         h ^= g;
426         h ^= g >> 13;
427     }
428     return( h % HASH_TABITEMS );
429 }
430 
FindResWord(const char * name,unsigned char size)431 unsigned FindResWord( const char *name, unsigned char size )
432 /**********************************************************/
433 /* search reserved word in hash table */
434 {
435     struct ReservedWord *inst;
436     unsigned i;
437 #ifdef BASEPTR
438     __segment seg = FP_SEG( resw_strings );
439 #endif
440 
441     for( i = resw_table[ get_hash( name, size ) ]; i != 0; i = inst->next ) {
442         inst = &ResWordTable[i];
443         /* check if the name matches the entry for this inst in AsmChars */
444         //if( name[ inst->len ] == NULLC && _strnicmp( name, inst->name, inst->len ) == 0) {
445         if( inst->len == size && _memicmp( name, GetPtr( inst, name ), inst->len ) == 0 ) {
446             return( i );
447         }
448     }
449     return( 0 );
450 }
451 
452 /* add reserved word to hash table */
453 
AddResWord(int token)454 static void AddResWord( int token )
455 /*********************************/
456 {
457     int i;
458     int old;
459     int curr;
460 #ifdef BASEPTR
461     __segment seg = FP_SEG( resw_strings );
462 #endif
463 
464     i = get_hash( ResWordTable[token].name, ResWordTable[token].len );
465 
466     /* sort the items of a line by length! */
467 
468     for( curr = resw_table[i], old = 0; curr != 0 && ResWordTable[curr].len <= ResWordTable[token].len; old = curr, curr = ResWordTable[curr].next );
469 
470     if ( old == 0 ) {
471         ResWordTable[token].next = resw_table[i];
472         resw_table[i] = token;
473     } else {
474         ResWordTable[token].next = ResWordTable[old].next;
475         ResWordTable[old].next = token;
476     }
477 
478     return;
479 }
480 
481 /* remove a reserved word from the hash table. */
482 
RemoveResWord(int token)483 static int RemoveResWord( int token )
484 /***********************************/
485 {
486     int i;
487     int old;
488     int curr;
489 #ifdef BASEPTR
490     __segment seg = FP_SEG( resw_strings );
491 #endif
492 
493     i = get_hash( ResWordTable[token].name, ResWordTable[token].len );
494 
495     for( curr = resw_table[i], old = 0 ; curr != 0 ; old = curr, curr = ResWordTable[curr].next )  {
496         if( curr == token ) {
497             if ( old != 0 )
498                 ResWordTable[old].next = ResWordTable[curr].next;
499             else
500                 resw_table[i] = ResWordTable[curr].next;
501             return( TRUE );
502         }
503     }
504     return( FALSE );
505 }
506 
507 #if RENAMEKEY
508 
509 struct rename_node {
510     struct rename_node *next;
511     const char *name; /* the original name in resw_strings[] */
512     uint_16 token; /* is either enum instr_token or enum special_token */
513     uint_8 length;
514 };
515 
516 /* Rename a keyword - used by OPTION RENAMEKEYWORD.
517  * - token: keyword to rename
518  * - newname: new name of keyword
519  * - length: length of new name
520  */
521 
RenameKeyword(unsigned token,const char * newname,uint_8 length)522 void RenameKeyword( unsigned token, const char *newname, uint_8 length )
523 /**********************************************************************/
524 {
525     struct rename_node *curr;
526     struct rename_node *prev;
527 
528     /* v2.11: do nothing if new name matches current name */
529     if ( ResWordTable[token].len == length && !_memicmp( newname, ResWordTable[token].name, length ) )
530         return;
531 
532     RemoveResWord( token );
533     /* if it is the first rename action for this keyword,
534      * the original name must be saved.
535      */
536     if ( ResWordTable[token].name >= resw_strings &&
537         ResWordTable[token].name < ( resw_strings + sizeof( resw_strings ) ) ) {
538         curr = LclAlloc( sizeof( struct rename_node ) );
539         curr->next = NULL;
540         curr->name = ResWordTable[token].name;
541         curr->token = token;
542         curr->length = ResWordTable[token].len;
543         if ( renamed_keys.head == NULL ) {
544             renamed_keys.head = renamed_keys.tail = curr;
545         } else {
546             ((struct rename_node *)renamed_keys.tail)->next = curr;
547             renamed_keys.tail = curr;
548         }
549     } else {
550         LclFree( (void *)ResWordTable[token].name );
551 #if 1
552         /* v2.11: search the original name. if the "new" names matches
553          * the original name, restore the name pointer */
554         for ( curr = renamed_keys.head, prev = NULL; curr; prev = curr ) {
555             if ( curr->token == token ) {
556                 if ( curr->length == length && !memcmp( newname, curr->name, length ) ) {
557                     if ( prev )
558                         prev->next = curr->next;
559                     else
560                         renamed_keys.head = curr->next;
561                     if ( renamed_keys.tail == curr )
562                         renamed_keys.tail = prev;
563                     ResWordTable[token].name = curr->name;
564                     ResWordTable[token].len = curr->length;
565                     AddResWord( token );
566                     return;
567                 }
568                 break;
569             }
570         }
571 #endif
572     }
573     ResWordTable[token].name = LclAlloc( length );
574     /* convert to lowercase? */
575     memcpy( (void *)ResWordTable[token].name, newname, length );
576     ResWordTable[token].len = length;
577     AddResWord( token );
578 }
579 
580 #endif
581 
582 #if AMD64_SUPPORT
583 
584 /* depending on 64bit on or off, some instructions must be added,
585  * some removed. Currently this is a bit hackish.
586  */
Set64Bit(bool newmode)587 void Set64Bit( bool newmode )
588 /***************************/
589 {
590     static const char *syscallname;   /* "true" syscall name stored here */
591     int token;
592     int i;
593 
594     if ( newmode != b64bit ) {
595         DebugMsg1(("Set64Bit(%u): mode is to change\n", newmode ));
596         if ( newmode != FALSE ) {
597             optable_idx[ T_INC - SPECIAL_LAST ]++;   /* skip the one-byte register INC */
598             optable_idx[ T_DEC - SPECIAL_LAST ]++;   /* skip the one-byte register DEC */
599             /*
600              * change SYSCALL to SYSCALL_ language in long mode.
601              * one cannot just change the name, since the hash value
602              * will differ!
603              */
604             RemoveResWord( T_SYSCALL );
605             syscallname = ResWordTable[T_SYSCALL].name; /* save the "true" name */
606             ResWordTable[T_SYSCALL].name = strSyscall_;
607             ResWordTable[T_SYSCALL].len++;
608             AddResWord( T_SYSCALL );
609 
610             for ( i = 0; i < sizeof( patchtab64 ) / sizeof( patchtab64[0] ); i++ )
611                 for( token = patchtab64[i]; ResWordTable[token].flags & RWF_X64; token++ )
612                     if ( !( ResWordTable[token].flags & RWF_DISABLED ) )
613                         AddResWord( token );
614             for ( i = 0; i < sizeof( patchtab32 ) / sizeof( patchtab32[0] ); i++ )
615                 for( token = patchtab32[i]; ResWordTable[token].flags & RWF_IA32; token++ )
616                     if ( !( ResWordTable[token].flags & RWF_DISABLED ) )
617                         RemoveResWord( token );
618             for ( i = 0; i < sizeof( patchtabr) / sizeof( patchtabr[0] ); i++ ) {
619                 optable_idx[ patchtabr[i].tok] = patchtabr[i].idx64;
620             }
621         } else  {
622             optable_idx[T_INC - SPECIAL_LAST]--;   /* restore the one-byte register INC */
623             optable_idx[T_DEC - SPECIAL_LAST]--;   /* restore the one-byte register DEC */
624 
625             for ( i = 0; i < sizeof( patchtab64 ) / sizeof( patchtab64[0] ); i++ )
626                 for( token = patchtab64[i]; ResWordTable[token].flags & RWF_X64; token++ )
627                     if ( !( ResWordTable[token].flags & RWF_DISABLED ) )
628                         RemoveResWord( token );
629             for ( i = 0; i < sizeof( patchtab32 ) / sizeof( patchtab32[0] ); i++ )
630                 for( token = patchtab32[i]; ResWordTable[token].flags & RWF_IA32; token++ )
631                     if ( !( ResWordTable[token].flags & RWF_DISABLED ) )
632                         AddResWord( token );
633             for ( i = 0; i < sizeof( patchtabr) / sizeof( patchtabr[0] ); i++ ) {
634                 optable_idx[patchtabr[i].tok] = patchtabr[i].idx32;
635             }
636 
637             /* change calling convention syscall_ back to syscall */
638             RemoveResWord( T_SYSCALL );
639             ResWordTable[T_SYSCALL].name = syscallname; /* restore "true" name */
640             ResWordTable[T_SYSCALL].len--;
641             AddResWord( T_SYSCALL );
642         }
643         b64bit = newmode;
644     }
645 }
646 #endif
647 
DisableKeyword(unsigned token)648 void DisableKeyword( unsigned token )
649 /***********************************/
650 {
651     if ( !( ResWordTable[token].flags & RWF_DISABLED ) ) {
652         RemoveResWord( token );
653         ResWordTable[token].next = 0;
654         ResWordTable[token].flags |= RWF_DISABLED;
655         if ( Removed.Head == 0 )
656             Removed.Head = Removed.Tail = token;
657         else {
658             ResWordTable[Removed.Tail].next = token;
659             Removed.Tail = token;
660         }
661     }
662 }
663 
664 /* check if a keyword is in the list of disabled words.
665  */
666 
IsKeywordDisabled(const char * name,int len)667 bool IsKeywordDisabled( const char *name, int len )
668 /*************************************************/
669 {
670     unsigned token;
671     for ( token = Removed.Head; token != 0; token = ResWordTable[token].next )
672         if( ResWordTable[token].name[ len ] == NULLC && _memicmp( name, ResWordTable[token].name, len ) == 0 )
673             return( TRUE );
674     return( FALSE );
675 }
676 
677 /* get current name of a reserved word.
678  * max size is 255.
679  */
680 
GetResWName(unsigned resword,char * buff)681 char *GetResWName( unsigned resword, char *buff )
682 /***********************************************/
683 {
684 #ifdef __I86__
685     static char intbuff[32];
686 #else
687     static char intbuff[256];
688 #endif
689     if ( !buff )
690         buff = intbuff;
691     memcpy( buff, ResWordTable[resword].name, ResWordTable[resword].len );
692     buff[ResWordTable[resword].len] = NULLC;
693     return( buff );
694 }
695 
696 /* ResWordsInit() initializes the reserved words hash array ( resw_table[] )
697  * and also the reserved words string pointers ( ResWordTable[].name + ResWordTable[].len )
698  */
699 
ResWordsInit(void)700 void ResWordsInit( void )
701 /***********************/
702 {
703     int i;
704     const char *p = resw_strings;
705 
706     /* exit immediately if table is already initialized */
707     if ( ResWordTable[1].name )
708         return;
709 
710     DebugMsg(("ResWordsInit() enter\n"));
711 
712     /* clear hash table */
713     memset( &resw_table, 0, sizeof( resw_table ) );
714 
715 #if AVXSUPP && AMD64_SUPPORT
716     /* currently these flags must be set manually, since the
717      * RWF_ flags aren't contained in instravx.h */
718     ResWordTable[T_VPEXTRQ].flags |= RWF_X64;
719     ResWordTable[T_VPINSRQ].flags |= RWF_X64;
720 #endif
721 
722     /* initialize ResWordTable[].name and .len.
723      * add keyword to hash table ( unless it is 64-bit only ).
724      * v2.09: start with index = 1, since index 0 is now T_NULL
725      */
726     for( i = 1; i < sizeof( ResWordTable ) / sizeof( ResWordTable[0] ); i++ ) {
727         ResWordTable[i].name = p;
728         p += ResWordTable[i].len;
729 #if AMD64_SUPPORT /* don't add the words specific to x64 */
730         if ( !(ResWordTable[i].flags & RWF_X64 ) )
731 #endif
732             AddResWord( i );
733     }
734     DebugMsg(("ResWordsInit() exit\n"));
735     return;
736 }
737 
738 /* ResWordsFini() is called once per module
739  * it restores the resword table
740  */
741 
ResWordsFini(void)742 void ResWordsFini( void )
743 /***********************/
744 {
745     int i;
746     int next;
747 #if RENAMEKEY
748     struct rename_node  *rencurr;
749 #endif
750 
751     DebugMsg(("ResWordsFini() enter\n"));
752 #if RENAMEKEY
753     /* restore renamed keywords.
754      * the keyword has to removed ( and readded ) from the hash table,
755      * since its position most likely will change.
756      */
757     for ( rencurr = renamed_keys.head; rencurr; ) {
758         struct rename_node *tmp = rencurr->next;
759         RemoveResWord( rencurr->token );
760         /* v2.06: this is the correct name to free */
761         LclFree( (void *)ResWordTable[rencurr->token].name );
762         ResWordTable[rencurr->token].name = rencurr->name;
763         ResWordTable[rencurr->token].len = rencurr->length;
764         AddResWord( rencurr->token );
765         DebugMsg(("ResWordsFini(): %s restored\n", GetResWName( rencurr->token, NULL ) ));
766         //LclFree( (void *)rencurr->name ); /* v2.06: this was the wrong one */
767         LclFree( rencurr );
768         rencurr = tmp;
769     }
770     renamed_keys.head = NULL;
771 #endif
772 
773     /* reenter disabled keywords */
774     for( i = Removed.Head; i != 0; i = next ) {
775         next = ResWordTable[i].next;
776         ResWordTable[i].flags &= ~RWF_DISABLED;
777 #if AMD64_SUPPORT /* don't add the words specific to x64 */
778         if ( !(ResWordTable[i].flags & RWF_X64 ) )
779 #endif
780             AddResWord( i );
781         DebugMsg(("ResWordsInit(): %s reenabled\n", GetResWName( i, NULL ) ));
782     }
783     Removed.Head = Removed.Tail = 0;
784 
785     return;
786 }
787 
788 #ifdef DEBUG_OUT
789 
DumpResWords(void)790 void DumpResWords( void )
791 /***********************/
792 {
793     int i;
794 
795     printf("SpecialTable\n");
796     printf("   # keyword             value   sflags  cpu val8 type flg len\n");
797     printf("--------------------------------------------------------------\n");
798     /* start with index 1 ( index 0 is T_NULL ) */
799     for ( i = 1; i < sizeof( SpecialTable ) / sizeof( SpecialTable[0] ); i++ ) {
800         printf("%4u %-16s %8X %8X %4X %4X  %2X  %2X %3u\n", i, GetResWName( i, NULL ),
801                SpecialTable[i].value, SpecialTable[i].sflags,
802                SpecialTable[i].cpu, SpecialTable[i].bytval,
803                SpecialTable[i].type, ResWordTable[i].flags, ResWordTable[i].len );
804     }
805     printf("--------------------------------------------------------------\n");
806 
807     printf("\nitems in InstrTable[]: %u\n", sizeof( InstrTable ) / sizeof( InstrTable[0] ) );
808     printf("items in optable_idx[]: %u, used by ResWordTable items %u-%u\n",
809            sizeof( optable_idx ) / sizeof( optable_idx[0] ), INS_FIRST_1 + 1, sizeof( ResWordTable ) / sizeof( ResWordTable[0] ) - 1 );
810 
811     printf("\nInstructionTable\n");
812     printf("   # keyword          cls cpu opc rmb b1 rmi pfx fst idx flg len\n");
813     printf("----------------------------------------------------------------\n");
814     for ( i = INS_FIRST_1 + 1; i < sizeof( ResWordTable ) / sizeof( ResWordTable[0] ); i++ ) {
815         const struct instr_item *ins = &InstrTable[IndexFromToken( i )];
816         printf("%4u %-16s %02X %4X  %02X  %02X %2u %X   %X   %u  %4u %3X %3u\n", i, GetResWName( i, NULL ),
817                ins->opclsidx,
818                ins->cpu, ins->opcode, ins->rm_byte, ins->byte1_info,
819                ins->rm_info, ins->allowed_prefix, ins->first,
820                IndexFromToken( i ), ResWordTable[i].flags, ResWordTable[i].len );
821     }
822     printf("----------------------------------------------------------------\n");
823 }
824 
DumpInstrStats(void)825 void DumpInstrStats( void )
826 /*************************/
827 {
828     unsigned            i;
829     int                 inst;
830     unsigned            count = 0;
831     unsigned            max = 0;
832     unsigned            curr = 0;
833     unsigned            num[8] = {0,0,0,0,0,0,0,0};
834 
835     if ( Options.dump_reswords_hash ) {
836         printf("\nReserved Word Hash Table\n");
837         printf("Idx keywords\n");
838         printf("---------------------------\n");
839     }
840 
841     for( i = 0; i < HASH_TABITEMS; i++ ) {
842         if ( Options.dump_reswords_hash )
843             printf("%3u ", i );
844         for( inst = resw_table[i], curr = 0; inst != 0; inst = ResWordTable[inst].next ) {
845             if ( Options.dump_reswords_hash )
846                 printf(" %-8s", GetResWName( inst, NULL ) );
847             curr++;
848         }
849         if ( Options.dump_reswords_hash )
850             printf("\n" );
851         count += curr;
852         if ( curr <= 7 )
853             num[curr]++;
854         if (max < curr)
855             max = curr;
856     }
857     if ( Options.dump_reswords_hash )
858         printf("---------------------------\n");
859     if ( Options.quiet == FALSE ) {
860         printf( "%u items in resw table, max items/line=%u ", count, max );
861         printf( "[0=%u 1=%u %u %u %u %u %u %u]\n", num[0], num[1], num[2], num[3], num[4], num[5], num[6], num[7] );
862     }
863 }
864 #endif
865