Home | History | Annotate | Download | only in x86
      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 
     87 enum 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 
     95 typedef 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  */
    120 typedef 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. */
    137 typedef 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 
    145 typedef enum {
    146     X86_NEAR = 1,
    147     X86_SHORT,
    148     X86_FAR,
    149     X86_TO
    150 } x86_parse_targetmod;
    151 
    152 typedef enum {
    153     JMP_NONE,
    154     JMP_SHORT,
    155     JMP_NEAR,
    156     JMP_SHORT_FORCED,
    157     JMP_NEAR_FORCED
    158 } x86_jmp_opcode_sel;
    159 
    160 typedef 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  */
    172 int 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 */
    177 typedef 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 
    197 void yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare,
    198                        yasm_bytecode *precbc);
    199 
    200 void yasm_x86__ea_set_disponly(x86_effaddr *x86_ea);
    201 x86_effaddr *yasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg,
    202                                      unsigned char *rex, unsigned int bits);
    203 x86_effaddr *yasm_x86__ea_create_imm
    204     (x86_effaddr *x86_ea, /*@keep@*/ yasm_expr *imm, unsigned int im_len);
    205 yasm_effaddr *yasm_x86__ea_create_expr(yasm_arch *arch,
    206                                        /*@keep@*/ yasm_expr *e);
    207 void yasm_x86__ea_destroy(yasm_effaddr *ea);
    208 void yasm_x86__ea_print(const yasm_effaddr *ea, FILE *f, int indent_level);
    209 
    210 void yasm_x86__bc_insn_opersize_override(yasm_bytecode *bc,
    211                                          unsigned int opersize);
    212 void yasm_x86__bc_insn_addrsize_override(yasm_bytecode *bc,
    213                                          unsigned int addrsize);
    214 void yasm_x86__bc_insn_set_lockrep_prefix(yasm_bytecode *bc,
    215                                           unsigned int prefix);
    216 
    217 /* Bytecode types */
    218 typedef 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 
    226 typedef struct x86_opcode {
    227     unsigned char opcode[3];        /* opcode */
    228     unsigned char len;
    229 } x86_opcode;
    230 
    231 typedef 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 
    265 typedef 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  */
    280 typedef 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 
    288 void yasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn);
    289 void yasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp);
    290 void yasm_x86__bc_transform_jmpfar(yasm_bytecode *bc, x86_jmpfar *jmpfar);
    291 
    292 void 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  */
    299 int 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 
    303 void yasm_x86__parse_cpu(yasm_arch_x86 *arch_x86, const char *cpuid,
    304                          size_t cpuid_len);
    305 
    306 yasm_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);
    309 yasm_arch_regtmod yasm_x86__parse_check_regtmod
    310     (yasm_arch *arch, const char *id, size_t id_len,
    311      /*@out@*/ uintptr_t *data);
    312 
    313 int 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);
    316 int 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 
    321 unsigned 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