Home | History | Annotate | Download | only in x86
      1 /*
      2  * x86 architecture description
      3  *
      4  *  Copyright (C) 2002-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 #include <util.h>
     28 
     29 #include <libyasm.h>
     30 
     31 #include "x86arch.h"
     32 
     33 
     34 yasm_arch_module yasm_x86_LTX_arch;
     35 
     36 
     37 static /*@only@*/ yasm_arch *
     38 x86_create(const char *machine, const char *parser,
     39            /*@out@*/ yasm_arch_create_error *error)
     40 {
     41     yasm_arch_x86 *arch_x86;
     42     unsigned int amd64_machine;
     43 
     44     *error = YASM_ARCH_CREATE_OK;
     45 
     46     if (yasm__strcasecmp(machine, "x86") == 0)
     47         amd64_machine = 0;
     48     else if (yasm__strcasecmp(machine, "amd64") == 0)
     49         amd64_machine = 1;
     50     else {
     51         *error = YASM_ARCH_CREATE_BAD_MACHINE;
     52         return NULL;
     53     }
     54 
     55     arch_x86 = yasm_xmalloc(sizeof(yasm_arch_x86));
     56 
     57     arch_x86->arch.module = &yasm_x86_LTX_arch;
     58 
     59     /* default to all instructions/features enabled */
     60     arch_x86->active_cpu = 0;
     61     arch_x86->cpu_enables_size = 1;
     62     arch_x86->cpu_enables = yasm_xmalloc(sizeof(wordptr));
     63     arch_x86->cpu_enables[0] = BitVector_Create(64, FALSE);
     64     BitVector_Fill(arch_x86->cpu_enables[0]);
     65 
     66     arch_x86->amd64_machine = amd64_machine;
     67     arch_x86->mode_bits = 0;
     68     arch_x86->force_strict = 0;
     69     arch_x86->default_rel = 0;
     70     arch_x86->gas_intel_mode = 0;
     71     arch_x86->nop = X86_NOP_BASIC;
     72 
     73     if (yasm__strcasecmp(parser, "nasm") == 0)
     74         arch_x86->parser = X86_PARSER_NASM;
     75     else if (yasm__strcasecmp(parser, "tasm") == 0)
     76         arch_x86->parser = X86_PARSER_TASM;
     77     else if (yasm__strcasecmp(parser, "gas") == 0
     78              || yasm__strcasecmp(parser, "gnu") == 0)
     79         arch_x86->parser = X86_PARSER_GAS;
     80     else {
     81         yasm_xfree(arch_x86);
     82         *error = YASM_ARCH_CREATE_BAD_PARSER;
     83         return NULL;
     84     }
     85 
     86     return (yasm_arch *)arch_x86;
     87 }
     88 
     89 static void
     90 x86_destroy(/*@only@*/ yasm_arch *arch)
     91 {
     92     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
     93     unsigned int i;
     94     for (i=0; i<arch_x86->cpu_enables_size; i++)
     95         BitVector_Destroy(arch_x86->cpu_enables[i]);
     96     yasm_xfree(arch_x86->cpu_enables);
     97     yasm_xfree(arch);
     98 }
     99 
    100 static const char *
    101 x86_get_machine(const yasm_arch *arch)
    102 {
    103     const yasm_arch_x86 *arch_x86 = (const yasm_arch_x86 *)arch;
    104     if (arch_x86->amd64_machine)
    105         return "amd64";
    106     else
    107         return "x86";
    108 }
    109 
    110 static unsigned int
    111 x86_get_address_size(const yasm_arch *arch)
    112 {
    113     const yasm_arch_x86 *arch_x86 = (const yasm_arch_x86 *)arch;
    114     if (arch_x86->mode_bits != 0)
    115         return arch_x86->mode_bits;
    116     if (arch_x86->amd64_machine)
    117         return 64;
    118     else
    119         return 32;
    120 }
    121 
    122 static int
    123 x86_set_var(yasm_arch *arch, const char *var, unsigned long val)
    124 {
    125     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
    126     if (yasm__strcasecmp(var, "mode_bits") == 0)
    127         arch_x86->mode_bits = (unsigned int)val;
    128     else if (yasm__strcasecmp(var, "force_strict") == 0)
    129         arch_x86->force_strict = (unsigned int)val;
    130     else if (yasm__strcasecmp(var, "default_rel") == 0) {
    131         if (arch_x86->mode_bits != 64)
    132             yasm_warn_set(YASM_WARN_GENERAL,
    133                           N_("ignoring default rel in non-64-bit mode"));
    134         else
    135             arch_x86->default_rel = (unsigned int)val;
    136     } else if (yasm__strcasecmp(var, "gas_intel_mode") == 0) {
    137         arch_x86->gas_intel_mode = (unsigned int)val;
    138     } else
    139         return 1;
    140     return 0;
    141 }
    142 
    143 static void
    144 x86_dir_cpu(yasm_object *object, yasm_valparamhead *valparams,
    145             yasm_valparamhead *objext_valparams, unsigned long line)
    146 {
    147     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
    148 
    149     yasm_valparam *vp;
    150     yasm_vps_foreach(vp, valparams) {
    151         /*@null@*/ /*@dependent@*/ const char *s = yasm_vp_string(vp);
    152         if (s)
    153             yasm_x86__parse_cpu(arch_x86, s, strlen(s));
    154         else if (vp->type == YASM_PARAM_EXPR) {
    155             const yasm_intnum *intcpu;
    156             intcpu = yasm_expr_get_intnum(&vp->param.e, 0);
    157             if (!intcpu)
    158                 yasm_error_set(YASM_ERROR_SYNTAX,
    159                                N_("invalid argument to [%s]"), "CPU");
    160             else {
    161                 char strcpu[16];
    162                 sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
    163                 yasm_x86__parse_cpu(arch_x86, strcpu, strlen(strcpu));
    164             }
    165         } else
    166             yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
    167                            "CPU");
    168     }
    169 }
    170 
    171 static void
    172 x86_dir_bits(yasm_object *object, yasm_valparamhead *valparams,
    173              yasm_valparamhead *objext_valparams, unsigned long line)
    174 {
    175     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
    176     yasm_valparam *vp;
    177     /*@only@*/ /*@null@*/ yasm_expr *e = NULL;
    178     const yasm_intnum *intn;
    179     long lval;
    180 
    181     if ((vp = yasm_vps_first(valparams)) && !vp->val &&
    182         (e = yasm_vp_expr(vp, object->symtab, line)) != NULL &&
    183         (intn = yasm_expr_get_intnum(&e, 0)) != NULL &&
    184         (lval = yasm_intnum_get_int(intn)) &&
    185         (lval == 16 || lval == 32 || lval == 64))
    186         arch_x86->mode_bits = (unsigned char)lval;
    187     else
    188         yasm_error_set(YASM_ERROR_VALUE, N_("invalid argument to [%s]"),
    189                        "BITS");
    190     if (e)
    191         yasm_expr_destroy(e);
    192 }
    193 
    194 static void
    195 x86_dir_code16(yasm_object *object, yasm_valparamhead *valparams,
    196                yasm_valparamhead *objext_valparams, unsigned long line)
    197 {
    198     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
    199     arch_x86->mode_bits = 16;
    200 }
    201 
    202 static void
    203 x86_dir_code32(yasm_object *object, yasm_valparamhead *valparams,
    204                yasm_valparamhead *objext_valparams, unsigned long line)
    205 {
    206     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
    207     arch_x86->mode_bits = 32;
    208 }
    209 
    210 static void
    211 x86_dir_code64(yasm_object *object, yasm_valparamhead *valparams,
    212                yasm_valparamhead *objext_valparams, unsigned long line)
    213 {
    214     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
    215     arch_x86->mode_bits = 64;
    216 }
    217 
    218 static const unsigned char **
    219 x86_get_fill(const yasm_arch *arch)
    220 {
    221     const yasm_arch_x86 *arch_x86 = (const yasm_arch_x86 *)arch;
    222 
    223     /* Fill patterns that GAS uses. */
    224     static const unsigned char fill16_1[1] =
    225         {0x90};                                 /* 1 - nop */
    226     static const unsigned char fill16_2[2] =
    227         {0x89, 0xf6};                           /* 2 - mov si, si */
    228     static const unsigned char fill16_3[3] =
    229         {0x8d, 0x74, 0x00};                     /* 3 - lea si, [si+byte 0] */
    230     static const unsigned char fill16_4[4] =
    231         {0x8d, 0xb4, 0x00, 0x00};               /* 4 - lea si, [si+word 0] */
    232     static const unsigned char fill16_5[5] =
    233         {0x90,                                  /* 5 - nop */
    234          0x8d, 0xb4, 0x00, 0x00};               /*     lea si, [si+word 0] */
    235     static const unsigned char fill16_6[6] =
    236         {0x89, 0xf6,                            /* 6 - mov si, si */
    237          0x8d, 0xbd, 0x00, 0x00};               /*     lea di, [di+word 0] */
    238     static const unsigned char fill16_7[7] =
    239         {0x8d, 0x74, 0x00,                      /* 7 - lea si, [si+byte 0] */
    240          0x8d, 0xbd, 0x00, 0x00};               /*     lea di, [di+word 0] */
    241     static const unsigned char fill16_8[8] =
    242         {0x8d, 0xb4, 0x00, 0x00,                /* 8 - lea si, [si+word 0] */
    243          0x8d, 0xbd, 0x00, 0x00};               /*     lea di, [di+word 0] */
    244     static const unsigned char fill16_9[9] =
    245         {0xeb, 0x07, 0x90, 0x90, 0x90, 0x90,    /* 9 - jmp $+9; nop fill */
    246          0x90, 0x90, 0x90};
    247     static const unsigned char fill16_10[10] =
    248         {0xeb, 0x08, 0x90, 0x90, 0x90, 0x90,    /* 10 - jmp $+10; nop fill */
    249          0x90, 0x90, 0x90, 0x90};
    250     static const unsigned char fill16_11[11] =
    251         {0xeb, 0x09, 0x90, 0x90, 0x90, 0x90,    /* 11 - jmp $+11; nop fill */
    252          0x90, 0x90, 0x90, 0x90, 0x90};
    253     static const unsigned char fill16_12[12] =
    254         {0xeb, 0x0a, 0x90, 0x90, 0x90, 0x90,    /* 12 - jmp $+12; nop fill */
    255          0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
    256     static const unsigned char fill16_13[13] =
    257         {0xeb, 0x0b, 0x90, 0x90, 0x90, 0x90,    /* 13 - jmp $+13; nop fill */
    258          0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
    259     static const unsigned char fill16_14[14] =
    260         {0xeb, 0x0c, 0x90, 0x90, 0x90, 0x90,    /* 14 - jmp $+14; nop fill */
    261          0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
    262     static const unsigned char fill16_15[15] =
    263         {0xeb, 0x0d, 0x90, 0x90, 0x90, 0x90,    /* 15 - jmp $+15; nop fill */
    264          0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
    265     static const unsigned char *fill16[16] =
    266     {
    267         NULL,      fill16_1,  fill16_2,  fill16_3,
    268         fill16_4,  fill16_5,  fill16_6,  fill16_7,
    269         fill16_8,  fill16_9,  fill16_10, fill16_11,
    270         fill16_12, fill16_13, fill16_14, fill16_15
    271     };
    272 
    273     static const unsigned char fill32_1[1] =
    274         {0x90};                              /* 1 - nop */
    275     static const unsigned char fill32_2[2] =
    276         {0x66, 0x90};                        /* 2 - xchg ax, ax (o16 nop) */
    277     static const unsigned char fill32_3[3] =
    278         {0x8d, 0x76, 0x00};                  /* 3 - lea esi, [esi+byte 0] */
    279     static const unsigned char fill32_4[4] =
    280         {0x8d, 0x74, 0x26, 0x00};            /* 4 - lea esi, [esi*1+byte 0] */
    281     static const unsigned char fill32_5[5] =
    282         {0x90,                               /* 5 - nop */
    283          0x8d, 0x74, 0x26, 0x00};            /*     lea esi, [esi*1+byte 0] */
    284     static const unsigned char fill32_6[6] =
    285         {0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00};/* 6 - lea esi, [esi+dword 0] */
    286     static const unsigned char fill32_7[7] =
    287         {0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, /* 7 - lea esi, [esi*1+dword 0] */
    288          0x00};
    289     static const unsigned char fill32_8[8] =
    290         {0x90,                               /* 8 - nop */
    291          0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, /*     lea esi, [esi*1+dword 0] */
    292          0x00};
    293 #if 0
    294     /* GAS uses these */
    295     static const unsigned char fill32_9[9] =
    296         {0x89, 0xf6,                         /* 9 - mov esi, esi */
    297          0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /*     lea edi, [edi*1+dword 0] */
    298          0x00};
    299     static const unsigned char fill32_10[10] =
    300         {0x8d, 0x76, 0x00,                   /* 10 - lea esi, [esi+byte 0] */
    301          0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /*      lea edi, [edi+dword 0] */
    302          0x00};
    303     static const unsigned char fill32_11[11] =
    304         {0x8d, 0x74, 0x26, 0x00,             /* 11 - lea esi, [esi*1+byte 0] */
    305          0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /*      lea edi, [edi*1+dword 0] */
    306          0x00};
    307     static const unsigned char fill32_12[12] =
    308         {0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00, /* 12 - lea esi, [esi+dword 0] */
    309          0x8d, 0xbf, 0x00, 0x00, 0x00, 0x00};/*      lea edi, [edi+dword 0] */
    310     static const unsigned char fill32_13[13] =
    311         {0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00, /* 13 - lea esi, [esi+dword 0] */
    312          0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /*      lea edi, [edi*1+dword 0] */
    313          0x00};
    314     static const unsigned char fill32_14[14] =
    315         {0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, /* 14 - lea esi, [esi*1+dword 0] */
    316          0x00,
    317          0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /*      lea edi, [edi*1+dword 0] */
    318          0x00};
    319 #else
    320     /* But on newer processors, these are recommended */
    321     static const unsigned char fill32_9[9] =
    322         {0xeb, 0x07, 0x90, 0x90, 0x90, 0x90, /* 9 - jmp $+9; nop fill */
    323          0x90, 0x90, 0x90};
    324     static const unsigned char fill32_10[10] =
    325         {0xeb, 0x08, 0x90, 0x90, 0x90, 0x90, /* 10 - jmp $+10; nop fill */
    326          0x90, 0x90, 0x90, 0x90};
    327     static const unsigned char fill32_11[11] =
    328         {0xeb, 0x09, 0x90, 0x90, 0x90, 0x90, /* 11 - jmp $+11; nop fill */
    329          0x90, 0x90, 0x90, 0x90, 0x90};
    330     static const unsigned char fill32_12[12] =
    331         {0xeb, 0x0a, 0x90, 0x90, 0x90, 0x90, /* 12 - jmp $+12; nop fill */
    332          0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
    333     static const unsigned char fill32_13[13] =
    334         {0xeb, 0x0b, 0x90, 0x90, 0x90, 0x90, /* 13 - jmp $+13; nop fill */
    335          0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
    336     static const unsigned char fill32_14[14] =
    337         {0xeb, 0x0c, 0x90, 0x90, 0x90, 0x90, /* 14 - jmp $+14; nop fill */
    338          0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
    339 #endif
    340     static const unsigned char fill32_15[15] =
    341         {0xeb, 0x0d, 0x90, 0x90, 0x90, 0x90, /* 15 - jmp $+15; nop fill */
    342          0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
    343     static const unsigned char *fill32[16] =
    344     {
    345         NULL,      fill32_1,  fill32_2,  fill32_3,
    346         fill32_4,  fill32_5,  fill32_6,  fill32_7,
    347         fill32_8,  fill32_9,  fill32_10, fill32_11,
    348         fill32_12, fill32_13, fill32_14, fill32_15
    349     };
    350 
    351     /* Long form nops available on more recent Intel and AMD processors */
    352     static const unsigned char fill32new_3[3] =
    353         {0x0f, 0x1f, 0x00};                         /* 3 - nop(3) */
    354     static const unsigned char fill32new_4[4] =
    355         {0x0f, 0x1f, 0x40, 0x00};                   /* 4 - nop(4) */
    356     static const unsigned char fill32new_5[5] =
    357         {0x0f, 0x1f, 0x44, 0x00, 0x00};             /* 5 - nop(5) */
    358     static const unsigned char fill32new_6[6] =
    359         {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00};       /* 6 - nop(6) */
    360     static const unsigned char fill32new_7[7] =
    361         {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}; /* 7 - nop(7) */
    362     static const unsigned char fill32new_8[8] =
    363         {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00,  /* 8 - nop(8) */
    364          0x00};
    365     static const unsigned char fill32new_9[9] =
    366         {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00,  /* 9 - nop(9) */
    367          0x00, 0x00};
    368 
    369     /* Longer forms preferred by Intel use repeated o16 prefixes */
    370     static const unsigned char fill32intel_10[10] =
    371         {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00,  /* 10 - o16; cs; nop */
    372          0x00, 0x00, 0x00};
    373     static const unsigned char fill32intel_11[11] =
    374         {0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00,  /* 11 - 2x o16; cs; nop */
    375          0x00, 0x00, 0x00, 0x00};
    376     static const unsigned char fill32intel_12[12] =
    377         {0x66, 0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84,  /* 12 - 3x o16; cs; nop */
    378          0x00, 0x00, 0x00, 0x00, 0x00};
    379     static const unsigned char fill32intel_13[13] =
    380         {0x66, 0x66, 0x66, 0x66, 0x2e, 0x0f, 0x1f,  /* 13 - 4x o16; cs; nop */
    381          0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
    382     static const unsigned char fill32intel_14[14] =
    383         {0x66, 0x66, 0x66, 0x66, 0x66, 0x2e, 0x0f,  /* 14 - 5x o16; cs; nop */
    384          0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
    385     static const unsigned char fill32intel_15[15] =
    386         {0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x2e,  /* 15 - 6x o16; cs; nop */
    387          0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
    388 
    389     /* Longer forms preferred by AMD use fewer o16 prefixes and no CS prefix;
    390      * Source: Software Optimisation Guide for AMD Family 10h
    391      * Processors 40546 revision 3.10 February 2009
    392      */
    393     static const unsigned char fill32amd_10[10] =
    394         {0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00,  /* 10 - nop(10) */
    395          0x00, 0x00, 0x00};
    396     static const unsigned char fill32amd_11[11] =
    397         {0x0f, 0x1f, 0x44, 0x00, 0x00,              /* 11 - nop(5) */
    398          0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00};       /*      nop(6) */
    399     static const unsigned char fill32amd_12[12] =
    400         {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00,        /* 12 - nop(6) */
    401          0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00};       /*      nop(6) */
    402     static const unsigned char fill32amd_13[13] =
    403         {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00,        /* 13 - nop(6) */
    404          0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}; /*      nop(7) */
    405     static const unsigned char fill32amd_14[14] =
    406         {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,  /* 14 - nop(7) */
    407          0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}; /*      nop(7) */
    408     static const unsigned char fill32amd_15[15] =
    409         {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,        /* 15 - nop(7) */
    410          0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}; /*      nop(8) */
    411 
    412     static const unsigned char *fill32_intel[16] =
    413     {
    414         NULL,           fill32_1,       fill32_2,       fill32new_3,
    415         fill32new_4,    fill32new_5,    fill32new_6,    fill32new_7,
    416         fill32new_8,    fill32new_9,    fill32intel_10, fill32intel_11,
    417         fill32intel_12, fill32intel_13, fill32intel_14, fill32intel_15
    418     };
    419     static const unsigned char *fill32_amd[16] =
    420     {
    421         NULL,           fill32_1,       fill32_2,       fill32new_3,
    422         fill32new_4,    fill32new_5,    fill32new_6,    fill32new_7,
    423         fill32new_8,    fill32new_9,    fill32amd_10,   fill32amd_11,
    424         fill32amd_12,   fill32amd_13,   fill32amd_14,   fill32amd_15
    425     };
    426 
    427     switch (arch_x86->mode_bits) {
    428         case 16:
    429             return fill16;
    430         case 32:
    431             if (arch_x86->nop == X86_NOP_INTEL)
    432                 return fill32_intel;
    433             else if (arch_x86->nop == X86_NOP_AMD)
    434                 return fill32_amd;
    435             else
    436                 return fill32;
    437         case 64:
    438             /* We know long nops are available in 64-bit mode; default to Intel
    439              * ones if unspecified (to match GAS behavior).
    440              */
    441             if (arch_x86->nop == X86_NOP_AMD)
    442                 return fill32_amd;
    443             else
    444                 return fill32_intel;
    445         default:
    446             yasm_error_set(YASM_ERROR_VALUE,
    447                            N_("Invalid mode_bits in x86_get_fill"));
    448             return NULL;
    449     }
    450 }
    451 
    452 unsigned int
    453 yasm_x86__get_reg_size(uintptr_t reg)
    454 {
    455     switch ((x86_expritem_reg_size)(reg & ~0xFUL)) {
    456         case X86_REG8:
    457         case X86_REG8X:
    458             return 8;
    459         case X86_REG16:
    460             return 16;
    461         case X86_REG32:
    462         case X86_CRREG:
    463         case X86_DRREG:
    464         case X86_TRREG:
    465             return 32;
    466         case X86_REG64:
    467         case X86_MMXREG:
    468             return 64;
    469         case X86_XMMREG:
    470             return 128;
    471         case X86_YMMREG:
    472             return 256;
    473         case X86_FPUREG:
    474             return 80;
    475         default:
    476             yasm_error_set(YASM_ERROR_VALUE, N_("unknown register size"));
    477     }
    478     return 0;
    479 }
    480 
    481 static unsigned int
    482 x86_get_reg_size(yasm_arch *arch, uintptr_t reg)
    483 {
    484     return yasm_x86__get_reg_size(reg);
    485 }
    486 
    487 static uintptr_t
    488 x86_reggroup_get_reg(yasm_arch *arch, uintptr_t reggroup,
    489                      unsigned long regindex)
    490 {
    491     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
    492     switch ((x86_expritem_reg_size)(reggroup & ~0xFUL)) {
    493         case X86_XMMREG:
    494         case X86_YMMREG:
    495             if (arch_x86->mode_bits == 64) {
    496                 if (regindex > 15)
    497                     return 0;
    498                 return reggroup | (regindex & 15);
    499             }
    500             /*@fallthrough@*/
    501         case X86_MMXREG:
    502         case X86_FPUREG:
    503             if (regindex > 7)
    504                 return 0;
    505             return reggroup | (regindex & 7);
    506         default:
    507             yasm_error_set(YASM_ERROR_VALUE, N_("bad register group"));
    508     }
    509     return 0;
    510 }
    511 
    512 static void
    513 x86_reg_print(yasm_arch *arch, uintptr_t reg, FILE *f)
    514 {
    515     static const char *name8[] = {"al","cl","dl","bl","ah","ch","dh","bh"};
    516     static const char *name8x[] = {
    517         "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
    518         "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
    519     };
    520     static const char *name16[] = {
    521         "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
    522         "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
    523     };
    524     static const char *name32[] = {
    525         "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
    526         "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
    527     };
    528     static const char *name64[] = {
    529         "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
    530         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
    531     };
    532 
    533     switch ((x86_expritem_reg_size)(reg & ~0xFUL)) {
    534         case X86_REG8:
    535             fprintf(f, "%s", name8[reg&0xF]);
    536             break;
    537         case X86_REG8X:
    538             fprintf(f, "%s", name8x[reg&0xF]);
    539             break;
    540         case X86_REG16:
    541             fprintf(f, "%s", name16[reg&0xF]);
    542             break;
    543         case X86_REG32:
    544             fprintf(f, "%s", name32[reg&0xF]);
    545             break;
    546         case X86_REG64:
    547             fprintf(f, "%s", name64[reg&0xF]);
    548             break;
    549         case X86_MMXREG:
    550             fprintf(f, "mm%d", (int)(reg&0xF));
    551             break;
    552         case X86_XMMREG:
    553             fprintf(f, "xmm%d", (int)(reg&0xF));
    554             break;
    555         case X86_YMMREG:
    556             fprintf(f, "ymm%d", (int)(reg&0xF));
    557             break;
    558         case X86_CRREG:
    559             fprintf(f, "cr%d", (int)(reg&0xF));
    560             break;
    561         case X86_DRREG:
    562             fprintf(f, "dr%d", (int)(reg&0xF));
    563             break;
    564         case X86_TRREG:
    565             fprintf(f, "tr%d", (int)(reg&0xF));
    566             break;
    567         case X86_FPUREG:
    568             fprintf(f, "st%d", (int)(reg&0xF));
    569             break;
    570         default:
    571             yasm_error_set(YASM_ERROR_VALUE, N_("unknown register size"));
    572     }
    573 }
    574 
    575 static void
    576 x86_segreg_print(yasm_arch *arch, uintptr_t segreg, FILE *f)
    577 {
    578     static const char *name[] = {"es","cs","ss","ds","fs","gs"};
    579     fprintf(f, "%s", name[segreg&7]);
    580 }
    581 
    582 /* Define x86 machines -- see arch.h for details */
    583 static const yasm_arch_machine x86_machines[] = {
    584     { "IA-32 and derivatives", "x86" },
    585     { "AMD64", "amd64" },
    586     { NULL, NULL }
    587 };
    588 
    589 static const yasm_directive x86_directives[] = {
    590     { "cpu",            "nasm", x86_dir_cpu,    YASM_DIR_ARG_REQUIRED },
    591     { "bits",           "nasm", x86_dir_bits,   YASM_DIR_ARG_REQUIRED },
    592     { ".code16",        "gas",  x86_dir_code16, YASM_DIR_ANY },
    593     { ".code32",        "gas",  x86_dir_code32, YASM_DIR_ANY },
    594     { ".code64",        "gas",  x86_dir_code64, YASM_DIR_ANY },
    595     { NULL, NULL, NULL, 0 }
    596 };
    597 
    598 /* Define arch structure -- see arch.h for details */
    599 yasm_arch_module yasm_x86_LTX_arch = {
    600     "x86 (IA-32 and derivatives), AMD64",
    601     "x86",
    602     x86_directives,
    603     x86_create,
    604     x86_destroy,
    605     x86_get_machine,
    606     x86_get_address_size,
    607     x86_set_var,
    608     yasm_x86__parse_check_insnprefix,
    609     yasm_x86__parse_check_regtmod,
    610     x86_get_fill,
    611     yasm_x86__floatnum_tobytes,
    612     yasm_x86__intnum_tobytes,
    613     x86_get_reg_size,
    614     x86_reggroup_get_reg,
    615     x86_reg_print,
    616     x86_segreg_print,
    617     yasm_x86__ea_create_expr,
    618     yasm_x86__ea_destroy,
    619     yasm_x86__ea_print,
    620     yasm_x86__create_empty_insn,
    621     x86_machines,
    622     "x86",
    623     16,
    624     1
    625 };
    626