jwasm/reswords.c
2014-06-18 19:16:56 +04:00

865 lines
30 KiB
C

/****************************************************************************
*
* This code is Public Domain.
*
* ========================================================================
*
* Description: reserved word handling, including hash table access
*
****************************************************************************/
#include "globals.h"
#include "memalloc.h"
#include "parser.h"
#include "reswords.h"
#include "expreval.h"
#include "condasm.h"
#include "codegen.h"
#ifdef __I86__
#include "i86.h"
#endif
//#define HASH_TABITEMS 211
#if AVXSUPP
#define HASH_TABITEMS 811
#else
#define HASH_TABITEMS 599
#endif
#if 0 // def __I86__
/* optionally, for JWASMR, use a void based pointer for the name field.
* However, this requires to deactivate the RENAMEKEYWORD option!
*/
#define GetPtr( x, y ) seg:>x->y
#define BASEPTR
#else
#define GetPtr( x, y ) x->y
#endif
/* reserved words hash table */
static uint_16 resw_table[ HASH_TABITEMS ];
/* define unary operand (LOW, HIGH, OFFSET, ...) type flags */
enum unary_operand_types {
#define res( value, func ) UOT_ ## value,
#include "unaryop.h"
#undef res
};
/* v2.06: the following operand combinations are used
* inside InstrTable[] only, they don't need to be known
* by the parser.
*/
enum operand_sets {
OP_R_MS = ( OP_R | OP_MS ),
OP_R8_M08 = ( OP_R8 | OP_M08 ),
OP_RGT8_MS = ( OP_RGT8 | OP_MS ),
OP_RGT8_MGT8 = ( OP_RGT8 | OP_MGT8 ),
OP_RMGT16 = ( OP_RGT16 | OP_MGT16 ),
OP_RGT16_M08 = ( OP_RGT16 | OP_M08 ),
OP_R16_R32 = ( OP_R16 | OP_R32 ),
OP_R16_M16 = ( OP_R16 | OP_M16 ),
OP_R32_M08 = ( OP_R32 | OP_M08 ),
OP_R32_M16 = ( OP_R32 | OP_M16 ),
OP_R32_M32 = ( OP_R32 | OP_M32 ),
#if AMD64_SUPPORT
OP_R16_R64 = ( OP_R16 | OP_R64 ),
OP_R64_M64 = ( OP_R64 | OP_M64 ),
OP_M16_M64 = ( OP_M16 | OP_M64 ),
#endif
OP_M16_M32 = ( OP_M16 | OP_M32 ),
OP_MMX_M64 = ( OP_MMX | OP_M64 ),
OP_XMM_M16 = ( OP_XMM | OP_M16 ),
OP_XMM_M32 = ( OP_XMM | OP_M32 ),
OP_XMM_M64 = ( OP_XMM | OP_M64 ),
OP_XMM_M128 = ( OP_XMM | OP_M128 ),
#if MASM_SSE_MEMX
/* extended Masm syntax: sometimes Masm accepts 2 mem types
* for the memory operand, although the mem access will always
* be QWORD/OWORD.
*/
OP_MMX_M64_08 = ( OP_MMX | OP_M64 | OP_M08 ),
OP_MMX_M64_16 = ( OP_MMX | OP_M64 | OP_M16 ),
OP_MMX_M64_32 = ( OP_MMX | OP_M64 | OP_M32 ),
OP_XMM_M128_08 = ( OP_XMM | OP_M128 | OP_M08 ),
OP_XMM_M128_16 = ( OP_XMM | OP_M128 | OP_M16 ),
OP_XMM_M128_32 = ( OP_XMM | OP_M128 | OP_M32 ),
OP_XMM_M128_64 = ( OP_XMM | OP_M128 | OP_M64 ),
#else
/* see macro OpCls() below */
#define OPC_MMXMMX_M64_08NONE OPC_MMXMMX_M64NONE
#define OPC_MMXMMX_M64_16NONE OPC_MMXMMX_M64NONE
#define OPC_MMXMMX_M64_32NONE OPC_MMXMMX_M64NONE
#define OPC_XMMXMM_M128_08NONE OPC_XMMXMM_M128NONE
#define OPC_XMMXMM_M128_16NONE OPC_XMMXMM_M128NONE
#define OPC_XMMXMM_M128_32NONE OPC_XMMXMM_M128NONE
#define OPC_XMMXMM_M128_64NONE OPC_XMMXMM_M128NONE
#endif
#if AVXSUPP
OP_YMM_M256 = ( OP_YMM | OP_M256 ),
#endif
};
/* v2.06: operand types have been removed from InstrTable[], they
* are stored now in their own table, opnd_clstab[], below.
* This will allow to add a 4th operand ( AVX ) more effectively.
*/
enum opnd_variants {
#define OpCls( op1, op2, op3 ) OPC_ ## op1 ## op2 ## op3,
#include "opndcls.h"
#undef OpCls
};
/* the tables to handle "reserved words" are now generated:
* 1. InstrTable: contains info for instructions.
* instructions may need multiple rows!
* 2. SpecialTable: contains info for reserved words which are
* NOT instructions. One row each.
* 3. optable_idx: array of indices for InstrTable.
* 4. resw_strings: strings of reserved words. No terminating x'00'!
* 5. ResWordTable: array of reserved words (name, name length, flags).
*
* Each reserved word has a "token" value assigned, which is a short integer.
* This integer can be used as index for:
* - SpecialTable
* - optable_idx ( needs adjustment, better use macro IndexFromToken() )
* - ResWordTable
*/
/* create InstrTable. */
#define OpCls( op1, op2, op3 ) OPC_ ## op1 ## op2 ## op3
const struct instr_item InstrTable[] = {
#define ins(tok, string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
{ opcls, byte1_info, prefix, 1, rm_info, op_dir, 0, cpu, opcode, rm_byte },
#define insx(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix,flgs) \
{ opcls, byte1_info, prefix, 1, rm_info, op_dir, 0, cpu, opcode, rm_byte },
#define insn(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
{ opcls, byte1_info, prefix, 0, rm_info, op_dir, 0, cpu, opcode, rm_byte },
#define insm(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
{ opcls, byte1_info, prefix, 1, rm_info, op_dir, 0, cpu, opcode, rm_byte },
#include "instruct.h"
#include "instr64.h"
ins (NULL,0,OpCls(NONE,NONE,NONE),0,0,0,0,0,0,0) /* last entry - needed for its ".first" (=1) field */
#undef insm
#undef insn
#undef insx
#undef ins
};
#undef OpCls
/* create SpecialTable. */
const struct special_item SpecialTable[] = {
{ 0, 0, 0, 0, 0 }, /* dummy entry for T_NULL */
#define res(tok, string, type, value, bytval, flags, cpu, sflags ) \
{ value, sflags, cpu, bytval, type },
#include "special.h"
#undef res
#define res(tok, string, value, bytval, flags, cpu, sflags ) \
{ value, sflags, cpu, bytval, RWT_DIRECTIVE },
#include "directve.h"
#undef res
};
/* define symbolic indices for InstrTable[] */
enum res_idx {
#define ins(tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _I,
#define insx(tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix,flgs) T_ ## tok ## _I,
#define insn(tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _ ## suffix,
#define insm(tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _ ## suffix,
#include "instruct.h"
#undef insm
#undef insn
#undef ins
#define ins(tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _I64,
#define insn(tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _ ## suffix ## _I64,
#define insm(tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _ ## suffix ## _I64,
#include "instr64.h"
#undef insm
#undef insn
#undef insx
#undef ins
//T_NULL_I /* v2.06: removed */
};
/* create optable_idx, the index array for InstrTable.
* This is needed because instructions often need more than
* one entry in InstrTable.
*/
uint_16 optable_idx[] = {
#define ins( tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix) T_ ## tok ## _I,
#define insx( tok, string, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix,flgs) T_ ## tok ## _I,
#define insn( tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix)
#define insm( tok, suffix, opcls, byte1_info, op_dir, rm_info, opcode, rm_byte, cpu, prefix)
#include "instruct.h"
#undef insm
#undef insn
#undef insx
#undef ins
/* v2.06: this was superfluous, because the additional entries for
* 64-bit are only needed in InstrTable[]. For optable_idx[], a
* patch is done (see patchtabr[])
*/
//#define ins(tok,string, op1,op2,op3, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) T_ ## tok ## _I64,
//#define insn(tok,suffix, op1,op2,op3, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) T_ ## tok ## _ ## suffix ## _I64,
//#define insm(tok,suffix, op1,op2,op3, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) T_ ## tok ## _ ## suffix ## _I64,
//#include "instr64.h"
//#undef insm
//#undef insn
//#undef ins
#if AVXSUPP
#define avxins( tok, string, cpu, flgs ) T_ ## tok ## _I,
#include "instravx.h"
#undef avxins
#endif
//T_NULL_I /* v2.06: also not needed */
};
/* table of instruction operand classes
*/
const struct opnd_class opnd_clstab[] = {
#define OpCls( op1, op2, op3 ) { { OP_ ## op1, OP_ ## op2 }, OP3_ ## op3 },
#include "opndcls.h"
#undef OpCls
};
/* create the strings for all reserved words */
static const char resw_strings[] = {
#define res(tok, string, type, value, bytval, flags, cpu, sflags) \
# string
#include "special.h"
#undef res
#define res(tok, string, value, bytval, flags, cpu, sflags) \
# string
#include "directve.h"
#undef res
#define ins(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
# string
#define insn(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix)
#define insm(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix)
#define insx(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix,flgs) \
# string
#include "instruct.h"
#if AVXSUPP
#define avxins( tok, string, cpu, flgs ) # string
#include "instravx.h"
#undef avxins
#endif
"syscall_" /* replacement for "syscall" language type in 64-bit */
};
#define strSyscall_ &resw_strings[sizeof(resw_strings)-9]
#undef insx
#undef insm
#undef insn
#undef ins
/* create the 'reserved words' table (ResWordTable).
* this table's entries will be used to create the instruction hash table.
* v2.11: RWF_SPECIAL flag removed:
* { 0, sizeof(#string)-1, RWF_SPECIAL | flags, NULL },
*/
struct ReservedWord ResWordTable[] = {
{ 0, 0, 0, NULL }, /* dummy entry for T_NULL */
#define res(tok, string, type, value, bytval, flags, cpu, sflags) \
{ 0, sizeof(#string)-1, flags, NULL },
#include "special.h"
#undef res
#define res(tok, string, value, bytval, flags, cpu, sflags) \
{ 0, sizeof(#string)-1, flags, NULL },
#include "directve.h"
#undef res
#define ins(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix) \
{ 0, sizeof(#string)-1, 0, NULL },
#define insn(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix)
#define insm(tok,suffix, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix)
#define insx(tok,string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix,flags) \
{ 0, sizeof(#string)-1, flags, NULL },
#include "instruct.h"
#undef insx
#undef insm
#undef insn
#undef ins
#if AVXSUPP
#define avxins( tok, string, cpu, flgs ) \
{ 0, sizeof(#string)-1, RWF_VEX, NULL },
#include "instravx.h"
#undef avxins
#endif
};
#if AVXSUPP
/* these is a special 1-byte array for vex-encoded instructions.
* it could probably be moved to InstrTable[] (there is an unused byte),
* but in fact it's the wrong place, since the content of vex_flags[]
* are associated with opcodes, not with instruction variants.
*/
const uint_8 vex_flags[] = {
/* flags for the AVX instructions in instruct.h. The order must
* be equal to the one in instruct.h! ( this is to be improved.)
* For a description of the VX_ flags see codegen.h
*/
VX_NND, /* VBROADCASTSS */
VX_NND, /* VBROADCASTSD */
VX_NND, /* VBROADCASTF128 */
VX_L, /* VBLENDVPD */
VX_L, /* VBLENDVPS */
0, /* VINSERTF128 */
VX_NND, /* VEXTRACTF128 */
VX_L, /* VMASKMOVPS */
VX_L, /* VMASKMOVPD */
0, /* VPBLENDVB */
VX_L|VX_IMM, /* VPERMILPD */
VX_L|VX_IMM, /* VPERMILPS */
/* VPERMIL2xx has been dropped */
//VX_L, /* VPERMIL2PD */
//VX_L, /* VPERMIL2PS */
0, /* VPERM2F128 */
VX_L|VX_NND, /* VTESTPS */
VX_L|VX_NND, /* VTESTPD */
VX_L, /* VZEROALL */
0, /* VZEROUPPER */
VX_NND, /* VCVTPD2DQ */
VX_NND, /* VCVTTPD2DQ */
VX_NND, /* VCVTPD2PS */
VX_NND, /* VMOVDDUP */
VX_L|VX_NND, /* VMOVMSKPD */ /* v2.11 */
VX_L|VX_NND, /* VMOVMSKPS */ /* v2.11 */
#define avxins( tok, string, cpu, flgs ) flgs,
#include "instravx.h"
#undef avxins
};
#endif
#if AMD64_SUPPORT
/* keywords to be added for 64-bit */
static const enum instr_token patchtab64[] = {
T_SPL, /* add x64 register part of special.h */
T_FRAME, /* add x64 reserved word part of special.h */
T_DOT_ALLOCSTACK, /* add x64 directive part of directve.h (win64) */
T_JRCXZ, /* branch instructions must be grouped together */
T_CDQE, /* add x64 part of instruct.h */
#if AVXSUPP
T_VPEXTRQ, /* add x64 part of instravx.h */
#endif
};
/* keywords to be removed for 64-bit */
static const enum instr_token patchtab32[] = {
T_TR3, /* registers invalid for IA32+ */
T_DOT_SAFESEH, /* directives invalid for IA32+ */
T_AAA, /* instructions invalid for IA32+ */
T_JCXZ, /* 1. branch instructions invalid for IA32+ */
T_LOOPW /* 2. branch instructions invalid for IA32+ */
};
struct replace_ins {
uint_16 tok; /* is an optable_idx[] index */
enum res_idx idx32;
enum res_idx idx64;
};
/* keyword entries to be changed for 64-bit (see instr64.h) */
static const struct replace_ins patchtabr[] = {
{ T_LGDT - SPECIAL_LAST, T_LGDT_I, T_LGDT_I64 },
{ T_LIDT - SPECIAL_LAST, T_LIDT_I, T_LIDT_I64 },
{ T_CALL - SPECIAL_LAST, T_CALL_I, T_CALL_I64 },
{ T_JMP - SPECIAL_LAST, T_JMP_I, T_JMP_I64 },
{ T_POP - SPECIAL_LAST, T_POP_I, T_POP_I64 }, /* v2.06: added */
{ T_PUSH - SPECIAL_LAST, T_PUSH_I, T_PUSH_I64 }, /* v2.06: added */
#if 1
/* with Masm, in 16/32-bit SLDT|SMSW|STR accept a WORD argument only -
* in 64-bit (ML64), 32- and 64-bit registers are also accepted!
*/
{ T_SLDT - SPECIAL_LAST, T_SLDT_I, T_SLDT_I64 },
{ T_SMSW - SPECIAL_LAST, T_SMSW_I, T_SMSW_I64 },
{ T_STR - SPECIAL_LAST, T_STR_I, T_STR_I64 },
#endif
#if VMXSUPP /* v2.09: added */
{ T_VMREAD - SPECIAL_LAST, T_VMREAD_I, T_VMREAD_I64 },
{ T_VMWRITE - SPECIAL_LAST, T_VMWRITE_I, T_VMWRITE_I64 },
#endif
};
#endif
#if RENAMEKEY
static struct qdesc renamed_keys = { NULL, NULL };
#endif
/* global queue of "disabled" reserved words.
* just indices of ResWordTable[] are used.
*/
static struct {
uint_16 Head;
uint_16 Tail;
} Removed = { 0, 0 };
#if AMD64_SUPPORT
static bool b64bit = FALSE; /* resw tables in 64bit mode? */
#endif
static unsigned get_hash( const char *s, unsigned char size )
/***********************************************************/
{
uint_32 h;
uint_32 g;
for( h = 0; size; size-- ) {
/* ( h & ~0x0fff ) == 0 is always true here */
h = (h << 3) + (*s++ | ' ');
g = h & ~0x1fff;
h ^= g;
h ^= g >> 13;
}
return( h % HASH_TABITEMS );
}
unsigned FindResWord( const char *name, unsigned char size )
/**********************************************************/
/* search reserved word in hash table */
{
struct ReservedWord *inst;
unsigned i;
#ifdef BASEPTR
__segment seg = FP_SEG( resw_strings );
#endif
for( i = resw_table[ get_hash( name, size ) ]; i != 0; i = inst->next ) {
inst = &ResWordTable[i];
/* check if the name matches the entry for this inst in AsmChars */
//if( name[ inst->len ] == NULLC && _strnicmp( name, inst->name, inst->len ) == 0) {
if( inst->len == size && _memicmp( name, GetPtr( inst, name ), inst->len ) == 0 ) {
return( i );
}
}
return( 0 );
}
/* add reserved word to hash table */
static void AddResWord( int token )
/*********************************/
{
int i;
int old;
int curr;
#ifdef BASEPTR
__segment seg = FP_SEG( resw_strings );
#endif
i = get_hash( ResWordTable[token].name, ResWordTable[token].len );
/* sort the items of a line by length! */
for( curr = resw_table[i], old = 0; curr != 0 && ResWordTable[curr].len <= ResWordTable[token].len; old = curr, curr = ResWordTable[curr].next );
if ( old == 0 ) {
ResWordTable[token].next = resw_table[i];
resw_table[i] = token;
} else {
ResWordTable[token].next = ResWordTable[old].next;
ResWordTable[old].next = token;
}
return;
}
/* remove a reserved word from the hash table. */
static int RemoveResWord( int token )
/***********************************/
{
int i;
int old;
int curr;
#ifdef BASEPTR
__segment seg = FP_SEG( resw_strings );
#endif
i = get_hash( ResWordTable[token].name, ResWordTable[token].len );
for( curr = resw_table[i], old = 0 ; curr != 0 ; old = curr, curr = ResWordTable[curr].next ) {
if( curr == token ) {
if ( old != 0 )
ResWordTable[old].next = ResWordTable[curr].next;
else
resw_table[i] = ResWordTable[curr].next;
return( TRUE );
}
}
return( FALSE );
}
#if RENAMEKEY
struct rename_node {
struct rename_node *next;
const char *name; /* the original name in resw_strings[] */
uint_16 token; /* is either enum instr_token or enum special_token */
uint_8 length;
};
/* Rename a keyword - used by OPTION RENAMEKEYWORD.
* - token: keyword to rename
* - newname: new name of keyword
* - length: length of new name
*/
void RenameKeyword( unsigned token, const char *newname, uint_8 length )
/**********************************************************************/
{
struct rename_node *curr;
struct rename_node *prev;
/* v2.11: do nothing if new name matches current name */
if ( ResWordTable[token].len == length && !_memicmp( newname, ResWordTable[token].name, length ) )
return;
RemoveResWord( token );
/* if it is the first rename action for this keyword,
* the original name must be saved.
*/
if ( ResWordTable[token].name >= resw_strings &&
ResWordTable[token].name < ( resw_strings + sizeof( resw_strings ) ) ) {
curr = LclAlloc( sizeof( struct rename_node ) );
curr->next = NULL;
curr->name = ResWordTable[token].name;
curr->token = token;
curr->length = ResWordTable[token].len;
if ( renamed_keys.head == NULL ) {
renamed_keys.head = renamed_keys.tail = curr;
} else {
((struct rename_node *)renamed_keys.tail)->next = curr;
renamed_keys.tail = curr;
}
} else {
LclFree( (void *)ResWordTable[token].name );
#if 1
/* v2.11: search the original name. if the "new" names matches
* the original name, restore the name pointer */
for ( curr = renamed_keys.head, prev = NULL; curr; prev = curr ) {
if ( curr->token == token ) {
if ( curr->length == length && !memcmp( newname, curr->name, length ) ) {
if ( prev )
prev->next = curr->next;
else
renamed_keys.head = curr->next;
if ( renamed_keys.tail == curr )
renamed_keys.tail = prev;
ResWordTable[token].name = curr->name;
ResWordTable[token].len = curr->length;
AddResWord( token );
return;
}
break;
}
}
#endif
}
ResWordTable[token].name = LclAlloc( length );
/* convert to lowercase? */
memcpy( (void *)ResWordTable[token].name, newname, length );
ResWordTable[token].len = length;
AddResWord( token );
}
#endif
#if AMD64_SUPPORT
/* depending on 64bit on or off, some instructions must be added,
* some removed. Currently this is a bit hackish.
*/
void Set64Bit( bool newmode )
/***************************/
{
static const char *syscallname; /* "true" syscall name stored here */
int token;
int i;
if ( newmode != b64bit ) {
DebugMsg1(("Set64Bit(%u): mode is to change\n", newmode ));
if ( newmode != FALSE ) {
optable_idx[ T_INC - SPECIAL_LAST ]++; /* skip the one-byte register INC */
optable_idx[ T_DEC - SPECIAL_LAST ]++; /* skip the one-byte register DEC */
/*
* change SYSCALL to SYSCALL_ language in long mode.
* one cannot just change the name, since the hash value
* will differ!
*/
RemoveResWord( T_SYSCALL );
syscallname = ResWordTable[T_SYSCALL].name; /* save the "true" name */
ResWordTable[T_SYSCALL].name = strSyscall_;
ResWordTable[T_SYSCALL].len++;
AddResWord( T_SYSCALL );
for ( i = 0; i < sizeof( patchtab64 ) / sizeof( patchtab64[0] ); i++ )
for( token = patchtab64[i]; ResWordTable[token].flags & RWF_X64; token++ )
if ( !( ResWordTable[token].flags & RWF_DISABLED ) )
AddResWord( token );
for ( i = 0; i < sizeof( patchtab32 ) / sizeof( patchtab32[0] ); i++ )
for( token = patchtab32[i]; ResWordTable[token].flags & RWF_IA32; token++ )
if ( !( ResWordTable[token].flags & RWF_DISABLED ) )
RemoveResWord( token );
for ( i = 0; i < sizeof( patchtabr) / sizeof( patchtabr[0] ); i++ ) {
optable_idx[ patchtabr[i].tok] = patchtabr[i].idx64;
}
} else {
optable_idx[T_INC - SPECIAL_LAST]--; /* restore the one-byte register INC */
optable_idx[T_DEC - SPECIAL_LAST]--; /* restore the one-byte register DEC */
for ( i = 0; i < sizeof( patchtab64 ) / sizeof( patchtab64[0] ); i++ )
for( token = patchtab64[i]; ResWordTable[token].flags & RWF_X64; token++ )
if ( !( ResWordTable[token].flags & RWF_DISABLED ) )
RemoveResWord( token );
for ( i = 0; i < sizeof( patchtab32 ) / sizeof( patchtab32[0] ); i++ )
for( token = patchtab32[i]; ResWordTable[token].flags & RWF_IA32; token++ )
if ( !( ResWordTable[token].flags & RWF_DISABLED ) )
AddResWord( token );
for ( i = 0; i < sizeof( patchtabr) / sizeof( patchtabr[0] ); i++ ) {
optable_idx[patchtabr[i].tok] = patchtabr[i].idx32;
}
/* change calling convention syscall_ back to syscall */
RemoveResWord( T_SYSCALL );
ResWordTable[T_SYSCALL].name = syscallname; /* restore "true" name */
ResWordTable[T_SYSCALL].len--;
AddResWord( T_SYSCALL );
}
b64bit = newmode;
}
}
#endif
void DisableKeyword( unsigned token )
/***********************************/
{
if ( !( ResWordTable[token].flags & RWF_DISABLED ) ) {
RemoveResWord( token );
ResWordTable[token].next = 0;
ResWordTable[token].flags |= RWF_DISABLED;
if ( Removed.Head == 0 )
Removed.Head = Removed.Tail = token;
else {
ResWordTable[Removed.Tail].next = token;
Removed.Tail = token;
}
}
}
/* check if a keyword is in the list of disabled words.
*/
bool IsKeywordDisabled( const char *name, int len )
/*************************************************/
{
unsigned token;
for ( token = Removed.Head; token != 0; token = ResWordTable[token].next )
if( ResWordTable[token].name[ len ] == NULLC && _memicmp( name, ResWordTable[token].name, len ) == 0 )
return( TRUE );
return( FALSE );
}
/* get current name of a reserved word.
* max size is 255.
*/
char *GetResWName( unsigned resword, char *buff )
/***********************************************/
{
#ifdef __I86__
static char intbuff[32];
#else
static char intbuff[256];
#endif
if ( !buff )
buff = intbuff;
memcpy( buff, ResWordTable[resword].name, ResWordTable[resword].len );
buff[ResWordTable[resword].len] = NULLC;
return( buff );
}
/* ResWordsInit() initializes the reserved words hash array ( resw_table[] )
* and also the reserved words string pointers ( ResWordTable[].name + ResWordTable[].len )
*/
void ResWordsInit( void )
/***********************/
{
int i;
const char *p = resw_strings;
/* exit immediately if table is already initialized */
if ( ResWordTable[1].name )
return;
DebugMsg(("ResWordsInit() enter\n"));
/* clear hash table */
memset( &resw_table, 0, sizeof( resw_table ) );
#if AVXSUPP && AMD64_SUPPORT
/* currently these flags must be set manually, since the
* RWF_ flags aren't contained in instravx.h */
ResWordTable[T_VPEXTRQ].flags |= RWF_X64;
ResWordTable[T_VPINSRQ].flags |= RWF_X64;
#endif
/* initialize ResWordTable[].name and .len.
* add keyword to hash table ( unless it is 64-bit only ).
* v2.09: start with index = 1, since index 0 is now T_NULL
*/
for( i = 1; i < sizeof( ResWordTable ) / sizeof( ResWordTable[0] ); i++ ) {
ResWordTable[i].name = p;
p += ResWordTable[i].len;
#if AMD64_SUPPORT /* don't add the words specific to x64 */
if ( !(ResWordTable[i].flags & RWF_X64 ) )
#endif
AddResWord( i );
}
DebugMsg(("ResWordsInit() exit\n"));
return;
}
/* ResWordsFini() is called once per module
* it restores the resword table
*/
void ResWordsFini( void )
/***********************/
{
int i;
int next;
#if RENAMEKEY
struct rename_node *rencurr;
#endif
DebugMsg(("ResWordsFini() enter\n"));
#if RENAMEKEY
/* restore renamed keywords.
* the keyword has to removed ( and readded ) from the hash table,
* since its position most likely will change.
*/
for ( rencurr = renamed_keys.head; rencurr; ) {
struct rename_node *tmp = rencurr->next;
RemoveResWord( rencurr->token );
/* v2.06: this is the correct name to free */
LclFree( (void *)ResWordTable[rencurr->token].name );
ResWordTable[rencurr->token].name = rencurr->name;
ResWordTable[rencurr->token].len = rencurr->length;
AddResWord( rencurr->token );
DebugMsg(("ResWordsFini(): %s restored\n", GetResWName( rencurr->token, NULL ) ));
//LclFree( (void *)rencurr->name ); /* v2.06: this was the wrong one */
LclFree( rencurr );
rencurr = tmp;
}
renamed_keys.head = NULL;
#endif
/* reenter disabled keywords */
for( i = Removed.Head; i != 0; i = next ) {
next = ResWordTable[i].next;
ResWordTable[i].flags &= ~RWF_DISABLED;
#if AMD64_SUPPORT /* don't add the words specific to x64 */
if ( !(ResWordTable[i].flags & RWF_X64 ) )
#endif
AddResWord( i );
DebugMsg(("ResWordsInit(): %s reenabled\n", GetResWName( i, NULL ) ));
}
Removed.Head = Removed.Tail = 0;
return;
}
#ifdef DEBUG_OUT
void DumpResWords( void )
/***********************/
{
int i;
printf("SpecialTable\n");
printf(" # keyword value sflags cpu val8 type flg len\n");
printf("--------------------------------------------------------------\n");
/* start with index 1 ( index 0 is T_NULL ) */
for ( i = 1; i < sizeof( SpecialTable ) / sizeof( SpecialTable[0] ); i++ ) {
printf("%4u %-16s %8X %8X %4X %4X %2X %2X %3u\n", i, GetResWName( i, NULL ),
SpecialTable[i].value, SpecialTable[i].sflags,
SpecialTable[i].cpu, SpecialTable[i].bytval,
SpecialTable[i].type, ResWordTable[i].flags, ResWordTable[i].len );
}
printf("--------------------------------------------------------------\n");
printf("\nitems in InstrTable[]: %u\n", sizeof( InstrTable ) / sizeof( InstrTable[0] ) );
printf("items in optable_idx[]: %u, used by ResWordTable items %u-%u\n",
sizeof( optable_idx ) / sizeof( optable_idx[0] ), INS_FIRST_1 + 1, sizeof( ResWordTable ) / sizeof( ResWordTable[0] ) - 1 );
printf("\nInstructionTable\n");
printf(" # keyword cls cpu opc rmb b1 rmi pfx fst idx flg len\n");
printf("----------------------------------------------------------------\n");
for ( i = INS_FIRST_1 + 1; i < sizeof( ResWordTable ) / sizeof( ResWordTable[0] ); i++ ) {
const struct instr_item *ins = &InstrTable[IndexFromToken( i )];
printf("%4u %-16s %02X %4X %02X %02X %2u %X %X %u %4u %3X %3u\n", i, GetResWName( i, NULL ),
ins->opclsidx,
ins->cpu, ins->opcode, ins->rm_byte, ins->byte1_info,
ins->rm_info, ins->allowed_prefix, ins->first,
IndexFromToken( i ), ResWordTable[i].flags, ResWordTable[i].len );
}
printf("----------------------------------------------------------------\n");
}
void DumpInstrStats( void )
/*************************/
{
unsigned i;
int inst;
unsigned count = 0;
unsigned max = 0;
unsigned curr = 0;
unsigned num[8] = {0,0,0,0,0,0,0,0};
if ( Options.dump_reswords_hash ) {
printf("\nReserved Word Hash Table\n");
printf("Idx keywords\n");
printf("---------------------------\n");
}
for( i = 0; i < HASH_TABITEMS; i++ ) {
if ( Options.dump_reswords_hash )
printf("%3u ", i );
for( inst = resw_table[i], curr = 0; inst != 0; inst = ResWordTable[inst].next ) {
if ( Options.dump_reswords_hash )
printf(" %-8s", GetResWName( inst, NULL ) );
curr++;
}
if ( Options.dump_reswords_hash )
printf("\n" );
count += curr;
if ( curr <= 7 )
num[curr]++;
if (max < curr)
max = curr;
}
if ( Options.dump_reswords_hash )
printf("---------------------------\n");
if ( Options.quiet == FALSE ) {
printf( "%u items in resw table, max items/line=%u ", count, max );
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] );
}
}
#endif