mirror of
https://github.com/NishiOwO/JWasm.git
synced 2025-04-21 16:54:39 +00:00
325 lines
11 KiB
C
325 lines
11 KiB
C
/****************************************************************************
|
|
*
|
|
* Open Watcom Project
|
|
*
|
|
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
|
*
|
|
* ========================================================================
|
|
*
|
|
* This file contains Original Code and/or Modifications of Original
|
|
* Code as defined in and that are subject to the Sybase Open Watcom
|
|
* Public License version 1.0 (the 'License'). You may not use this file
|
|
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
|
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
|
* provided with the Original Code and Modifications, and is also
|
|
* available at www.sybase.com/developer/opensource.
|
|
*
|
|
* The Original Code and all software distributed under the License are
|
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
|
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
|
* NON-INFRINGEMENT. Please see the License for the specific language
|
|
* governing rights and limitations under the License.
|
|
*
|
|
* ========================================================================
|
|
*
|
|
* Description: Parser items
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifndef PARSER_H
|
|
#define PARSER_H
|
|
|
|
#include "operands.h"
|
|
#include "symbols.h"
|
|
#include "token.h"
|
|
|
|
/* define tokens for SpecialTable (registers, operators, ... ) */
|
|
enum special_token {
|
|
T_NULL,
|
|
#define res(token, string, type, value, bytval, flags, cpu, sflags) T_ ## token ,
|
|
#include "special.h"
|
|
#undef res
|
|
/* define tokens for SpecialTable (directives) */
|
|
#define res(token, string, value, bytval, flags, cpu, sflags) T_ ## token ,
|
|
#include "directve.h"
|
|
#undef res
|
|
SPECIAL_LAST
|
|
};
|
|
|
|
/* define tokens for instruction table (InstrTable[] in reswords.c) */
|
|
|
|
enum instr_token {
|
|
INS_FIRST_1 = SPECIAL_LAST - 1, /* to ensure tokens are unique */
|
|
#define ins(token, string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix ) T_ ## token ,
|
|
#define insx(token, string, opcls, byte1_info,op_dir,rm_info,opcode,rm_byte,cpu,prefix,flgs ) T_ ## token ,
|
|
#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
|
|
#if AVXSUPP
|
|
#define VEX_START T_VBROADCASTSS /* first VEX encoded item */
|
|
#define avxins(token, string, cpu, flgs ) T_V ## token ,
|
|
#include "instravx.h"
|
|
#undef avxins
|
|
#endif
|
|
};
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* queue of symbols */
|
|
struct symbol_queue {
|
|
struct dsym *head;
|
|
struct dsym *tail;
|
|
};
|
|
|
|
enum queue_type {
|
|
TAB_UNDEF = 0,
|
|
TAB_EXT, /* externals (EXTERNDEF, EXTERN, COMM, PROTO ) */
|
|
TAB_SEG, /* SEGMENT items */
|
|
TAB_GRP, /* GROUP items */
|
|
TAB_PROC, /* PROC items */
|
|
TAB_ALIAS, /* ALIAS items */
|
|
TAB_LAST,
|
|
};
|
|
|
|
/* several lists, see enum queue_type above */
|
|
extern struct symbol_queue SymTables[];
|
|
|
|
/*
|
|
values for <rm_info> (3 bits)
|
|
000 -> has rm_byte with w-, d- and/or s-bit in opcode
|
|
001( no_RM ) -> no rm_byte - may have w-bit
|
|
010( no_WDS ) -> has rm_byte, but w-bit, d-bit, s-bit of opcode are absent
|
|
011( R_in_OP ) -> no rm_byte, reg field (if any) is included in opcode
|
|
*/
|
|
enum rm_info {
|
|
no_RM = 0x1,
|
|
no_WDS = 0x2,
|
|
R_in_OP = 0x3,
|
|
};
|
|
|
|
/* values for <allowed_prefix> (3 bits) */
|
|
enum allowed_prefix {
|
|
// AP_NO_PREFIX= 0x00, /* value 0 means "normal" */
|
|
AP_LOCK = 0x01,
|
|
AP_REP = 0x02,
|
|
AP_REPxx = 0x03,
|
|
AP_FWAIT = 0x04,
|
|
AP_NO_FWAIT = 0x05
|
|
};
|
|
|
|
/* values for field type in special_item.
|
|
* it should match order of T_REGISTER - T_RES_ID in token.h
|
|
*/
|
|
|
|
enum special_type {
|
|
RWT_REG = 2, /* same value as for T_REG */
|
|
RWT_DIRECTIVE,
|
|
RWT_UNARY_OP,
|
|
RWT_BINARY_OP,
|
|
RWT_STYPE,
|
|
RWT_RES_ID
|
|
};
|
|
|
|
// values for sflags if register
|
|
enum op1_flags {
|
|
SFR_SIZMSK = 0x1F, /* size in bits 0-4 */
|
|
SFR_IREG = 0x20,
|
|
SFR_SSBASED = 0x40, /* v2.11: added */
|
|
};
|
|
|
|
#if AMD64_SUPPORT
|
|
enum rex_bits {
|
|
REX_B = 1, /* regno 0-7 <-> 8-15 of ModR/M or SIB base */
|
|
REX_X = 2, /* regno 0-7 <-> 8-15 of SIB index */
|
|
REX_R = 4, /* regno 0-7 <-> 8-15 of ModR/M REG */
|
|
REX_W = 8 /* wide 32 <-> 64 */
|
|
};
|
|
#endif
|
|
|
|
/* operand classes. this table is defined in reswords.c.
|
|
* index into this array is member opclsidx in instr_item.
|
|
* v2.06: data removed from struct instr_item.
|
|
*/
|
|
struct opnd_class {
|
|
enum operand_type opnd_type[2]; /* operands 1 + 2 */
|
|
unsigned char opnd_type_3rd; /* operand 3 */
|
|
};
|
|
|
|
/* instr_item is the structure used to store instructions
|
|
* in InstrTable (instruct.h).
|
|
* Most compilers will use unsigned type for enums, just OW
|
|
* allows to use the smallest size possible.
|
|
*/
|
|
|
|
struct instr_item {
|
|
//enum operand_type opnd_type[2]; /* operands 1 + 2 */
|
|
//unsigned char opnd_type_3rd; /* operand 3 */
|
|
unsigned char opclsidx; /* v2.06: index for opnd_clstab */
|
|
unsigned char byte1_info; /* flags for 1st byte */
|
|
unsigned char
|
|
allowed_prefix : 3, /* allowed prefix */
|
|
first : 1, /* 1=opcode's first entry */
|
|
rm_info : 3, /* info on r/m byte */
|
|
opnd_dir : 1; /* operand direction */
|
|
unsigned char reserved; /* not used yet */
|
|
#ifdef __WATCOMC__
|
|
enum cpu_info cpu; /* CPU type */
|
|
#else
|
|
unsigned short cpu;
|
|
#endif
|
|
unsigned char opcode; /* opcode byte */
|
|
unsigned char rm_byte; /* mod_rm_byte */
|
|
};
|
|
|
|
/* special_item is the structure used to store directives and
|
|
* other reserved words in SpecialTable (special.h).
|
|
*/
|
|
struct special_item {
|
|
unsigned value;
|
|
unsigned sflags;
|
|
#ifdef __WATCOMC__
|
|
enum cpu_info cpu; /* CPU type */
|
|
#else
|
|
uint_16 cpu; /* CPU type */
|
|
#endif
|
|
uint_8 bytval;
|
|
#ifdef __WATCOMC__
|
|
enum special_type type;
|
|
#else
|
|
uint_8 type;
|
|
#endif
|
|
};
|
|
|
|
#define GetRegNo( x ) SpecialTable[x].bytval
|
|
#define GetSflagsSp( x ) SpecialTable[x].sflags
|
|
#define GetValueSp( x ) SpecialTable[x].value
|
|
#define GetMemtypeSp( x ) SpecialTable[x].bytval
|
|
#define GetCpuSp( x ) SpecialTable[x].cpu
|
|
|
|
/* values for <value> if type == RWT_DIRECTIVE */
|
|
enum directive_flags {
|
|
DF_CEXPR = 0x01, /* avoid '<' being used as string delimiter (.IF, ...) */
|
|
DF_STRPARM = 0x02, /* directive expects string param(s) (IFB, IFDIF, ...) */
|
|
/* enclose strings in <> in macro expansion step */
|
|
DF_NOEXPAND = 0x04, /* don't expand params for directive (PURGE, FOR, IFDEF, ...) */
|
|
DF_LABEL = 0x08, /* directive requires a label */
|
|
DF_NOSTRUC = 0x10, /* directive not allowed inside structs/unions */
|
|
DF_NOCONCAT = 0x20, /* don't concat line */
|
|
DF_PROC = 0x40, /* directive triggers prologue generation */
|
|
DF_STORE = 0x80, /* FASTPASS: directive triggers line store */
|
|
DF_CGEN = 0x100 /* directive generates lines */
|
|
};
|
|
|
|
/* values for <bytval> if type == RWT_DIRECTIVE */
|
|
#define res(token, function) DRT_ ## token ,
|
|
enum directive_type {
|
|
#include "dirtype.h"
|
|
};
|
|
#undef res
|
|
|
|
#define MAX_OPND 3
|
|
|
|
struct opnd_item {
|
|
enum operand_type type;
|
|
union {
|
|
struct {
|
|
int_32 data32l;
|
|
int_32 data32h; /* needed for OP_I48 and OP_I64 */
|
|
};
|
|
uint_64 data64;
|
|
};
|
|
struct fixup *InsFixup;
|
|
};
|
|
|
|
/* code_info describes the current instruction. It's the communication
|
|
* structure between parser and code generator.
|
|
*/
|
|
struct code_info {
|
|
struct {
|
|
enum instr_token ins; /* prefix before instruction, e.g. lock, rep, repnz */
|
|
enum assume_segreg RegOverride;/* segment override (0=ES,1=CS,2=SS,3=DS,...) */
|
|
#if AMD64_SUPPORT
|
|
unsigned char rex;
|
|
#endif
|
|
unsigned char adrsiz:1; /* address size prefix 0x67 is to be emitted */
|
|
unsigned char opsiz:1; /* operand size prefix 0x66 is to be emitted */
|
|
} prefix;
|
|
const struct instr_item *pinstr; /* current pointer into InstrTable */
|
|
enum instr_token token;
|
|
enum memtype mem_type; /* byte / word / etc. NOT near/far */
|
|
struct opnd_item opnd[MAX_OPND];
|
|
unsigned char rm_byte;
|
|
unsigned char sib;
|
|
unsigned char Ofssize;
|
|
unsigned char opc_or;
|
|
#if AVXSUPP
|
|
unsigned char vexregop; /* in based-1 format (0=empty) */
|
|
#endif
|
|
union {
|
|
unsigned char flags;
|
|
struct {
|
|
unsigned char iswide:1; /* 0=byte, 1=word/dword/qword */
|
|
unsigned char isdirect:1; /* 1=direct addressing mode */
|
|
unsigned char isfar:1; /* CALL/JMP far */
|
|
unsigned char const_size_fixed:1; /* v2.01 */
|
|
#if AMD64_SUPPORT
|
|
unsigned char x86hi_used:1; /* AH,BH,CH,DH used */
|
|
unsigned char x64lo_used:1; /* SPL,BPL,SIL,DIL used */
|
|
#endif
|
|
unsigned char undef_sym:1; /* v2.06b: struct member is forward ref */
|
|
};
|
|
};
|
|
};
|
|
|
|
#define OPND1 0
|
|
#define OPND2 1
|
|
#define OPND3 2
|
|
|
|
/* branch instructions are still sorted:
|
|
* CALL, JMP, Jcc, J[e|r]CXZ, LOOP, LOOPcc
|
|
*/
|
|
|
|
#define IS_CALL( inst ) ( inst == T_CALL )
|
|
#define IS_JMPCALL( inst ) ( inst == T_CALL || inst == T_JMP )
|
|
#define IS_JMP( inst ) ( inst >= T_JMP && inst < T_LOOP )
|
|
#define IS_JCC( inst ) ( inst > T_JMP && inst < T_JCXZ )
|
|
#define IS_BRANCH( inst ) ( inst >= T_CALL && inst < T_LOOP )
|
|
#define IS_ANY_BRANCH( inst ) ( inst >= T_CALL && inst <= T_LOOPNZW )
|
|
#define IS_XCX_BRANCH( inst ) ( inst >= T_JCXZ && inst <= T_LOOPNZW )
|
|
|
|
#define IS_OPER_32( s ) ( s->Ofssize ? ( s->prefix.opsiz == FALSE ) : ( s->prefix.opsiz == TRUE ))
|
|
|
|
/* globals */
|
|
//extern struct asym WordSize;
|
|
//#define CurrWordSize WordSize.value
|
|
extern const struct instr_item InstrTable[]; /* instruction table */
|
|
extern const struct special_item SpecialTable[]; /* rest of res words */
|
|
extern uint_16 optable_idx[]; /* helper, access thru IndexFromToken() only */
|
|
|
|
#define IndexFromToken( tok ) optable_idx[ ( tok ) - SPECIAL_LAST ]
|
|
|
|
extern int SizeFromMemtype( enum memtype, int, struct asym * );
|
|
extern ret_code MemtypeFromSize( int, enum memtype * );
|
|
extern int SizeFromRegister( int );
|
|
extern ret_code GetLangType( int *, struct asm_tok[], enum lang_type * );
|
|
|
|
extern void sym_add_table( struct symbol_queue *, struct dsym * );
|
|
extern void sym_remove_table( struct symbol_queue *, struct dsym * );
|
|
extern void sym_ext2int( struct asym * );
|
|
|
|
extern int OperandSize( enum operand_type, const struct code_info * );
|
|
extern void set_frame( const struct asym *sym );
|
|
extern void set_frame2( const struct asym *sym );
|
|
extern ret_code ParseLine( struct asm_tok[] );
|
|
extern void ProcessFile( struct asm_tok[] );
|
|
|
|
extern void WritePreprocessedLine( const char * );
|
|
|
|
#endif
|