uasm 1.0.9+2.57

A library to build the UASM compiler, for usage in build scripts.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
/****************************************************************************
*
*                            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,
	AP_BND      = 0x06
};

/* 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 */
    SFR_YMMMASK = 0x3F, /* added by habran */
    SFR_ZMMMASK = 0x7F, /* added by habran */
};
/* --        Reserved    P0[3 : 2] Must be 0
 * --        Fixed Value P1[10]    Must be 1
 * EVEX.mm   Compressed legacy escape P[1: 0] Identical to low two bits of VEX.mmmmm
 * EVEX.pp   Compressed legacy prefix P[9 : 8] Identical to VEX.pp
 * EVEX.RXB  Next-8 register specifier modifier P[7 : 5] Combine with ModR/M.reg, ModR/M.rm (base, index/vidx)
 * EVEXR     High-16 register specifier modifier P[4] Combine with EVEX.R and ModR/M.reg
 * EVEXX     High-16 register specifier modifier P[6] Combine with EVEX.B and ModR/M.rm, when SIB/VSIB absent
 * EVEX.vvvv NDS register specifier P[14 : 11] Same as VEX.vvvv
 * EVEXV     High-16 NDS/VIDX register specifier P[19] Combine with EVEX.vvvv or when VSIB present
 * EVEX.aaa  Embedded opmask register specifier P[18 : 16]
 * EVEX.W    Osize promotion/Opcode extension P[15]
 * EVEX.b    Broadcast/RC/SAE Context P[20]
 * EVEX.LL  Vector length/RC P[22 : 21]
 * EVEX.z    Zeroing/Merging P[23]
 */
#define EVEX_P0RMASK    0x80 
#define EVEX_P0XMASK    0x40 
#define EVEX_P0BMASK    0x20 
#define EVEX_P0R1MASK   0x10 
#define EVEX_P0MMMASK   0x03 
#define EVEX_P1WMASK    0x80
#define EVEX_P1VVVV     0x78 
#define EVEX_P1PPMASK   0x03 
#define EVEX_P2ZMASK    0x80 
#define EVEX_P2L1MASK   0x40 
#define EVEX_P2LMASK    0x20 
#define EVEX_P2BMASK    0x10 
#define EVEX_P2VMASK    0x08 
#define EVEX_P2AAAMASK  0x07
#define EVEX_P2LLMASK   0x60
#define W1            0x8000
 /* RXBR00MM,  WVVVV1PP,  ZLLBVAAA, MDREGR/M */
#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 {
    unsigned short	opclsidx;			/* v2.06: index for opnd_clstab */
    unsigned char	byte1_info;			/* flags for 1st byte */
    unsigned short	allowed_prefix;		/* allowed prefix */
    unsigned char	first;		        /* 1=opcode's first entry */
    unsigned char	rm_info;	        /* info on r/m byte */
    unsigned char	opnd_dir;	        /* operand direction */
    unsigned short	prefix;				/* used for EVEX */
    unsigned short	cpu;
    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 4

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;
	const char        *tokenPtr;
};

/* compressed tuple types upper bits 4,3,2,1,0 of resw_strings[].prefix : tuple & 0x1F  */
enum ttypes {
    FV    =  1,
    HV    =  2,
    FVM   =  3,
    T1S8  =  4,
    T1S16 =  5,
    T1S   =  6,
    T1F32 =  7,
    T1F64 = 10,
    T2    = 11,
    T4    = 12,
    T8    = 13,
    HVM   = 14,
    QVM   = 15,
    OVM   = 16,
    T128  = 17,
    DUP   = 20
};
/* compressed memory size bits 7,6,5 of resw_strings[].prefix: first 5 >> xSIZE and than 1 << xSIZE  */
enum mtypes {
    BSIZE  = 0x00, //  1
    WSIZE  = 0x20, //  2
    DSIZE  = 0x40, //  4 
    QSIZE  = 0x60, //  8 
    XSIZE  = 0x80, // 16 
    YSIZE  = 0xA0, // 32 
    ZSIZE  = 0xC0  // 64 
};
enum indextypes {
    IXSZ  = 0x0000,
    IYSZ  = 0x0100,
    IZSZ  = 0x0200,
};
/* 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;
    unsigned char   first_byte;        /* added for 2.46  for 0xC4 or 0xC5 */
    /* habran */
#if AVXSUPP
    unsigned char   basetype;
    unsigned char   reg1;
    unsigned char   reg2;
    unsigned char   reg3;
    unsigned char   indexreg;
    unsigned char   basereg;
    unsigned int    r1type;
    unsigned int    r2type;
          int_32   vexconst;
    unsigned char   vexregop;   /* in based-1 format (0=empty) */
    /* habran */
    unsigned int   indextype;  /* Used for EVEX */
    unsigned char   evex_flag; /* for EVEX instructions */
    unsigned char   evex_p0;
    unsigned char   evex_p1;
    unsigned char   evex_p2;
    unsigned char   zreg;
             bool   tuple;     /* For EVEX Compressed Disp8*N Encoding */
			 bool   isptr;
    unsigned char   evex_sae;  /* EVEX Static Rounding Mode */
#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
#define OPND4 3

/* 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