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