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