x86arch.c 24 KB

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