1/*
2 * x86 Architecture header file
3 *
4 *  Copyright (C) 2001-2007  Peter Johnson
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27#ifndef YASM_X86ARCH_H
28#define YASM_X86ARCH_H
29
30#include <libyasm/bitvect.h>
31
32/* Available CPU feature flags */
33#define CPU_Any     0       /* Any old cpu will do */
34#define CPU_086     CPU_Any
35#define CPU_186     1       /* i186 or better required */
36#define CPU_286     2       /* i286 or better required */
37#define CPU_386     3       /* i386 or better required */
38#define CPU_486     4       /* i486 or better required */
39#define CPU_586     5       /* i585 or better required */
40#define CPU_686     6       /* i686 or better required */
41#define CPU_P3      7       /* Pentium3 or better required */
42#define CPU_P4      8       /* Pentium4 or better required */
43#define CPU_IA64    9       /* IA-64 or better required */
44#define CPU_K6      10      /* AMD K6 or better required */
45#define CPU_Athlon  11      /* AMD Athlon or better required */
46#define CPU_Hammer  12      /* AMD Sledgehammer or better required */
47#define CPU_FPU     13      /* FPU support required */
48#define CPU_MMX     14      /* MMX support required */
49#define CPU_SSE     15      /* Streaming SIMD extensions required */
50#define CPU_SSE2    16      /* Streaming SIMD extensions 2 required */
51#define CPU_SSE3    17      /* Streaming SIMD extensions 3 required */
52#define CPU_3DNow   18      /* 3DNow! support required */
53#define CPU_Cyrix   19      /* Cyrix-specific instruction */
54#define CPU_AMD     20      /* AMD-specific inst. (older than K6) */
55#define CPU_SMM     21      /* System Management Mode instruction */
56#define CPU_Prot    22      /* Protected mode only instruction */
57#define CPU_Undoc   23      /* Undocumented instruction */
58#define CPU_Obs     24      /* Obsolete instruction */
59#define CPU_Priv    25      /* Priveleged instruction */
60#define CPU_SVM     26      /* Secure Virtual Machine instruction */
61#define CPU_PadLock 27      /* VIA PadLock instruction */
62#define CPU_EM64T   28      /* Intel EM64T or better */
63#define CPU_SSSE3   29      /* Streaming SIMD extensions 3 required */
64#define CPU_SSE41   30      /* Streaming SIMD extensions 4.1 required */
65#define CPU_SSE42   31      /* Streaming SIMD extensions 4.2 required */
66#define CPU_SSE4a   32      /* AMD Streaming SIMD extensions 4a required */
67#define CPU_XSAVE   33      /* Intel XSAVE instructions */
68#define CPU_AVX     34      /* Intel Advanced Vector Extensions */
69#define CPU_FMA     35      /* Intel Fused-Multiply-Add Extensions */
70#define CPU_AES     36      /* AES instruction */
71#define CPU_CLMUL   37      /* PCLMULQDQ instruction */
72#define CPU_MOVBE   38      /* MOVBE instruction */
73#define CPU_XOP     39      /* AMD XOP extensions */
74#define CPU_FMA4    40      /* AMD Fused-Multiply-Add extensions */
75#define CPU_F16C    41      /* Intel float-16 instructions */
76#define CPU_FSGSBASE 42     /* Intel FSGSBASE instructions */
77#define CPU_RDRAND  43      /* Intel RDRAND instruction */
78#define CPU_XSAVEOPT 44     /* Intel XSAVEOPT instruction */
79#define CPU_EPTVPID 45      /* Intel INVEPT, INVVPID instructions */
80#define CPU_SMX     46      /* Intel SMX instruction (GETSEC) */
81#define CPU_AVX2    47      /* Intel AVX2 instructions */
82#define CPU_BMI1    48      /* Intel BMI1 instructions */
83#define CPU_BMI2    49      /* Intel BMI2 instructions */
84#define CPU_INVPCID 50      /* Intel INVPCID instruction */
85#define CPU_LZCNT   51      /* Intel LZCNT instruction */
86
87enum x86_parser_type {
88    X86_PARSER_NASM = 0,
89    X86_PARSER_TASM = 1,
90    X86_PARSER_GAS = 2
91};
92
93#define PARSER(arch) (((arch)->parser == X86_PARSER_GAS && (arch)->gas_intel_mode) ? X86_PARSER_NASM : (arch)->parser)
94
95typedef struct yasm_arch_x86 {
96    yasm_arch_base arch;        /* base structure */
97
98    /* What instructions/features are enabled? */
99    unsigned int active_cpu;        /* active index into cpu_enables table */
100    unsigned int cpu_enables_size;  /* size of cpu_enables table */
101    wordptr *cpu_enables;
102
103    unsigned int amd64_machine;
104    enum x86_parser_type parser;
105    unsigned int mode_bits;
106    unsigned int force_strict;
107    unsigned int default_rel;
108    unsigned int gas_intel_mode;
109
110    enum {
111        X86_NOP_BASIC = 0,
112        X86_NOP_INTEL = 1,
113        X86_NOP_AMD = 2
114    } nop;
115} yasm_arch_x86;
116
117/* 0-15 (low 4 bits) used for register number, stored in same data area.
118 * Note 8-15 are only valid for some registers, and only in 64-bit mode.
119 */
120typedef enum {
121    X86_REG8 = 0x1<<4,
122    X86_REG8X = 0x2<<4,     /* 64-bit mode only, REX prefix version of REG8 */
123    X86_REG16 = 0x3<<4,
124    X86_REG32 = 0x4<<4,
125    X86_REG64 = 0x5<<4,     /* 64-bit mode only */
126    X86_FPUREG = 0x6<<4,
127    X86_MMXREG = 0x7<<4,
128    X86_XMMREG = 0x8<<4,
129    X86_YMMREG = 0x9<<4,
130    X86_CRREG = 0xA<<4,
131    X86_DRREG = 0xB<<4,
132    X86_TRREG = 0xC<<4,
133    X86_RIP = 0xD<<4        /* 64-bit mode only, always RIP (regnum ignored) */
134} x86_expritem_reg_size;
135
136/* Low 8 bits are used for the prefix value, stored in same data area. */
137typedef enum {
138    X86_LOCKREP = 1<<8,
139    X86_ADDRSIZE = 2<<8,
140    X86_OPERSIZE = 3<<8,
141    X86_SEGREG = 4<<8,
142    X86_REX = 5<<8
143} x86_parse_insn_prefix;
144
145typedef enum {
146    X86_NEAR = 1,
147    X86_SHORT,
148    X86_FAR,
149    X86_TO
150} x86_parse_targetmod;
151
152typedef enum {
153    JMP_NONE,
154    JMP_SHORT,
155    JMP_NEAR,
156    JMP_SHORT_FORCED,
157    JMP_NEAR_FORCED
158} x86_jmp_opcode_sel;
159
160typedef enum {
161    X86_REX_W = 3,
162    X86_REX_R = 2,
163    X86_REX_X = 1,
164    X86_REX_B = 0
165} x86_rex_bit_pos;
166
167/* Sets REX (4th bit) and 3 LS bits from register size/number.  Returns 1 if
168 * impossible to fit reg into REX, otherwise returns 0.  Input parameter rexbit
169 * indicates bit of REX to use if REX is needed.  Will not modify REX if not
170 * in 64-bit mode or if it wasn't needed to express reg.
171 */
172int yasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3,
173                               uintptr_t reg, unsigned int bits,
174                               x86_rex_bit_pos rexbit);
175
176/* Effective address type */
177typedef struct x86_effaddr {
178    yasm_effaddr ea;            /* base structure */
179
180    /* VSIB uses the normal SIB byte, but this flag enables it. */
181    unsigned char vsib_mode;    /* 0 if not, 1 if XMM, 2 if YMM */
182
183    /* How the spare (register) bits in Mod/RM are handled:
184     * Even if valid_modrm=0, the spare bits are still valid (don't overwrite!)
185     * They're set in bytecode_create_insn().
186     */
187    unsigned char modrm;
188    unsigned char valid_modrm;  /* 1 if Mod/RM byte currently valid, 0 if not */
189    unsigned char need_modrm;   /* 1 if Mod/RM byte needed, 0 if not */
190
191    unsigned char sib;
192    unsigned char valid_sib;    /* 1 if SIB byte currently valid, 0 if not */
193    unsigned char need_sib;     /* 1 if SIB byte needed, 0 if not,
194                                   0xff if unknown */
195} x86_effaddr;
196
197void yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare,
198                       yasm_bytecode *precbc);
199
200void yasm_x86__ea_set_disponly(x86_effaddr *x86_ea);
201x86_effaddr *yasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg,
202                                     unsigned char *rex, unsigned int bits);
203x86_effaddr *yasm_x86__ea_create_imm
204    (x86_effaddr *x86_ea, /*@keep@*/ yasm_expr *imm, unsigned int im_len);
205yasm_effaddr *yasm_x86__ea_create_expr(yasm_arch *arch,
206                                       /*@keep@*/ yasm_expr *e);
207void yasm_x86__ea_destroy(yasm_effaddr *ea);
208void yasm_x86__ea_print(const yasm_effaddr *ea, FILE *f, int indent_level);
209
210void yasm_x86__bc_insn_opersize_override(yasm_bytecode *bc,
211                                         unsigned int opersize);
212void yasm_x86__bc_insn_addrsize_override(yasm_bytecode *bc,
213                                         unsigned int addrsize);
214void yasm_x86__bc_insn_set_lockrep_prefix(yasm_bytecode *bc,
215                                          unsigned int prefix);
216
217/* Bytecode types */
218typedef struct x86_common {
219    unsigned char addrsize;         /* 0 or =mode_bits => no override */
220    unsigned char opersize;         /* 0 or =mode_bits => no override */
221    unsigned char lockrep_pre;      /* 0 indicates no prefix */
222
223    unsigned char mode_bits;
224} x86_common;
225
226typedef struct x86_opcode {
227    unsigned char opcode[3];        /* opcode */
228    unsigned char len;
229} x86_opcode;
230
231typedef struct x86_insn {
232    x86_common common;              /* common x86 information */
233    x86_opcode opcode;
234
235    /*@null@*/ x86_effaddr *x86_ea; /* effective address */
236
237    /*@null@*/ yasm_value *imm;     /* immediate or relative value */
238
239    unsigned char def_opersize_64;  /* default operand size in 64-bit mode */
240    unsigned char special_prefix;   /* "special" prefix (0=none) */
241
242    unsigned char rex;          /* REX AMD64 extension, 0 if none,
243                                   0xff if not allowed (high 8 bit reg used) */
244
245    /* Postponed (from parsing to later binding) action options. */
246    enum {
247        /* None */
248        X86_POSTOP_NONE = 0,
249
250        /* Instructions that take a sign-extended imm8 as well as imm values
251         * (eg, the arith instructions and a subset of the imul instructions)
252         * should set this and put the imm8 form as the "normal" opcode (in
253         * the first one or two bytes) and non-imm8 form in the second or
254         * third byte of the opcode.
255         */
256        X86_POSTOP_SIGNEXT_IMM8,
257
258        /* Override any attempt at address-size override to 16 bits, and never
259         * generate a prefix.  This is used for the ENTER opcode.
260         */
261        X86_POSTOP_ADDRESS16
262    } postop;
263} x86_insn;
264
265typedef struct x86_jmp {
266    x86_common common;          /* common x86 information */
267    x86_opcode shortop, nearop;
268
269    yasm_value target;          /* jump target */
270
271    /* which opcode are we using? */
272    /* The *FORCED forms are specified in the source as such */
273    x86_jmp_opcode_sel op_sel;
274} x86_jmp;
275
276/* Direct (immediate) FAR jumps ONLY; indirect FAR jumps get turned into
277 * x86_insn bytecodes; relative jumps turn into x86_jmp bytecodes.
278 * This bytecode is not legal in 64-bit mode.
279 */
280typedef struct x86_jmpfar {
281    x86_common common;          /* common x86 information */
282    x86_opcode opcode;
283
284    yasm_value segment;         /* target segment */
285    yasm_value offset;          /* target offset */
286} x86_jmpfar;
287
288void yasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn);
289void yasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp);
290void yasm_x86__bc_transform_jmpfar(yasm_bytecode *bc, x86_jmpfar *jmpfar);
291
292void yasm_x86__bc_apply_prefixes
293    (x86_common *common, unsigned char *rex, unsigned int def_opersize_64,
294     unsigned int num_prefixes, uintptr_t *prefixes);
295
296/* Check an effective address.  Returns 0 if EA was successfully determined,
297 * 1 if invalid EA, or 2 if indeterminate EA.
298 */
299int yasm_x86__expr_checkea
300    (x86_effaddr *x86_ea, unsigned char *addrsize, unsigned int bits,
301     int address16_op, unsigned char *rex, yasm_bytecode *bc);
302
303void yasm_x86__parse_cpu(yasm_arch_x86 *arch_x86, const char *cpuid,
304                         size_t cpuid_len);
305
306yasm_arch_insnprefix yasm_x86__parse_check_insnprefix
307    (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
308     /*@out@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
309yasm_arch_regtmod yasm_x86__parse_check_regtmod
310    (yasm_arch *arch, const char *id, size_t id_len,
311     /*@out@*/ uintptr_t *data);
312
313int yasm_x86__floatnum_tobytes
314    (yasm_arch *arch, const yasm_floatnum *flt, unsigned char *buf,
315     size_t destsize, size_t valsize, size_t shift, int warn);
316int yasm_x86__intnum_tobytes
317    (yasm_arch *arch, const yasm_intnum *intn, unsigned char *buf,
318     size_t destsize, size_t valsize, int shift, const yasm_bytecode *bc,
319     int warn);
320
321unsigned int yasm_x86__get_reg_size(uintptr_t reg);
322
323/*@only@*/ yasm_bytecode *yasm_x86__create_empty_insn(yasm_arch *arch,
324                                                      unsigned long line);
325#endif
326