instructions.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // SPDX-License-Identifier: GPL-2.0
  2. static struct ins x86__instructions[] = {
  3. { .name = "adc", .ops = &mov_ops, },
  4. { .name = "adcb", .ops = &mov_ops, },
  5. { .name = "adcl", .ops = &mov_ops, },
  6. { .name = "add", .ops = &mov_ops, },
  7. { .name = "addl", .ops = &mov_ops, },
  8. { .name = "addq", .ops = &mov_ops, },
  9. { .name = "addsd", .ops = &mov_ops, },
  10. { .name = "addw", .ops = &mov_ops, },
  11. { .name = "and", .ops = &mov_ops, },
  12. { .name = "andb", .ops = &mov_ops, },
  13. { .name = "andl", .ops = &mov_ops, },
  14. { .name = "andpd", .ops = &mov_ops, },
  15. { .name = "andps", .ops = &mov_ops, },
  16. { .name = "andq", .ops = &mov_ops, },
  17. { .name = "andw", .ops = &mov_ops, },
  18. { .name = "bsr", .ops = &mov_ops, },
  19. { .name = "bt", .ops = &mov_ops, },
  20. { .name = "btr", .ops = &mov_ops, },
  21. { .name = "bts", .ops = &mov_ops, },
  22. { .name = "btsq", .ops = &mov_ops, },
  23. { .name = "call", .ops = &call_ops, },
  24. { .name = "callq", .ops = &call_ops, },
  25. { .name = "cmovbe", .ops = &mov_ops, },
  26. { .name = "cmove", .ops = &mov_ops, },
  27. { .name = "cmovae", .ops = &mov_ops, },
  28. { .name = "cmp", .ops = &mov_ops, },
  29. { .name = "cmpb", .ops = &mov_ops, },
  30. { .name = "cmpl", .ops = &mov_ops, },
  31. { .name = "cmpq", .ops = &mov_ops, },
  32. { .name = "cmpw", .ops = &mov_ops, },
  33. { .name = "cmpxch", .ops = &mov_ops, },
  34. { .name = "cmpxchg", .ops = &mov_ops, },
  35. { .name = "cs", .ops = &mov_ops, },
  36. { .name = "dec", .ops = &dec_ops, },
  37. { .name = "decl", .ops = &dec_ops, },
  38. { .name = "divsd", .ops = &mov_ops, },
  39. { .name = "divss", .ops = &mov_ops, },
  40. { .name = "gs", .ops = &mov_ops, },
  41. { .name = "imul", .ops = &mov_ops, },
  42. { .name = "inc", .ops = &dec_ops, },
  43. { .name = "incl", .ops = &dec_ops, },
  44. { .name = "ja", .ops = &jump_ops, },
  45. { .name = "jae", .ops = &jump_ops, },
  46. { .name = "jb", .ops = &jump_ops, },
  47. { .name = "jbe", .ops = &jump_ops, },
  48. { .name = "jc", .ops = &jump_ops, },
  49. { .name = "jcxz", .ops = &jump_ops, },
  50. { .name = "je", .ops = &jump_ops, },
  51. { .name = "jecxz", .ops = &jump_ops, },
  52. { .name = "jg", .ops = &jump_ops, },
  53. { .name = "jge", .ops = &jump_ops, },
  54. { .name = "jl", .ops = &jump_ops, },
  55. { .name = "jle", .ops = &jump_ops, },
  56. { .name = "jmp", .ops = &jump_ops, },
  57. { .name = "jmpq", .ops = &jump_ops, },
  58. { .name = "jna", .ops = &jump_ops, },
  59. { .name = "jnae", .ops = &jump_ops, },
  60. { .name = "jnb", .ops = &jump_ops, },
  61. { .name = "jnbe", .ops = &jump_ops, },
  62. { .name = "jnc", .ops = &jump_ops, },
  63. { .name = "jne", .ops = &jump_ops, },
  64. { .name = "jng", .ops = &jump_ops, },
  65. { .name = "jnge", .ops = &jump_ops, },
  66. { .name = "jnl", .ops = &jump_ops, },
  67. { .name = "jnle", .ops = &jump_ops, },
  68. { .name = "jno", .ops = &jump_ops, },
  69. { .name = "jnp", .ops = &jump_ops, },
  70. { .name = "jns", .ops = &jump_ops, },
  71. { .name = "jnz", .ops = &jump_ops, },
  72. { .name = "jo", .ops = &jump_ops, },
  73. { .name = "jp", .ops = &jump_ops, },
  74. { .name = "jpe", .ops = &jump_ops, },
  75. { .name = "jpo", .ops = &jump_ops, },
  76. { .name = "jrcxz", .ops = &jump_ops, },
  77. { .name = "js", .ops = &jump_ops, },
  78. { .name = "jz", .ops = &jump_ops, },
  79. { .name = "lea", .ops = &mov_ops, },
  80. { .name = "lock", .ops = &lock_ops, },
  81. { .name = "mov", .ops = &mov_ops, },
  82. { .name = "movapd", .ops = &mov_ops, },
  83. { .name = "movaps", .ops = &mov_ops, },
  84. { .name = "movb", .ops = &mov_ops, },
  85. { .name = "movdqa", .ops = &mov_ops, },
  86. { .name = "movdqu", .ops = &mov_ops, },
  87. { .name = "movl", .ops = &mov_ops, },
  88. { .name = "movq", .ops = &mov_ops, },
  89. { .name = "movsd", .ops = &mov_ops, },
  90. { .name = "movslq", .ops = &mov_ops, },
  91. { .name = "movss", .ops = &mov_ops, },
  92. { .name = "movupd", .ops = &mov_ops, },
  93. { .name = "movups", .ops = &mov_ops, },
  94. { .name = "movw", .ops = &mov_ops, },
  95. { .name = "movzbl", .ops = &mov_ops, },
  96. { .name = "movzwl", .ops = &mov_ops, },
  97. { .name = "mulsd", .ops = &mov_ops, },
  98. { .name = "mulss", .ops = &mov_ops, },
  99. { .name = "nop", .ops = &nop_ops, },
  100. { .name = "nopl", .ops = &nop_ops, },
  101. { .name = "nopw", .ops = &nop_ops, },
  102. { .name = "or", .ops = &mov_ops, },
  103. { .name = "orb", .ops = &mov_ops, },
  104. { .name = "orl", .ops = &mov_ops, },
  105. { .name = "orps", .ops = &mov_ops, },
  106. { .name = "orq", .ops = &mov_ops, },
  107. { .name = "pand", .ops = &mov_ops, },
  108. { .name = "paddq", .ops = &mov_ops, },
  109. { .name = "pcmpeqb", .ops = &mov_ops, },
  110. { .name = "por", .ops = &mov_ops, },
  111. { .name = "rclb", .ops = &mov_ops, },
  112. { .name = "rcll", .ops = &mov_ops, },
  113. { .name = "retq", .ops = &ret_ops, },
  114. { .name = "sbb", .ops = &mov_ops, },
  115. { .name = "sbbl", .ops = &mov_ops, },
  116. { .name = "sete", .ops = &mov_ops, },
  117. { .name = "sub", .ops = &mov_ops, },
  118. { .name = "subl", .ops = &mov_ops, },
  119. { .name = "subq", .ops = &mov_ops, },
  120. { .name = "subsd", .ops = &mov_ops, },
  121. { .name = "subw", .ops = &mov_ops, },
  122. { .name = "test", .ops = &mov_ops, },
  123. { .name = "testb", .ops = &mov_ops, },
  124. { .name = "testl", .ops = &mov_ops, },
  125. { .name = "ucomisd", .ops = &mov_ops, },
  126. { .name = "ucomiss", .ops = &mov_ops, },
  127. { .name = "vaddsd", .ops = &mov_ops, },
  128. { .name = "vandpd", .ops = &mov_ops, },
  129. { .name = "vmovdqa", .ops = &mov_ops, },
  130. { .name = "vmovq", .ops = &mov_ops, },
  131. { .name = "vmovsd", .ops = &mov_ops, },
  132. { .name = "vmulsd", .ops = &mov_ops, },
  133. { .name = "vorpd", .ops = &mov_ops, },
  134. { .name = "vsubsd", .ops = &mov_ops, },
  135. { .name = "vucomisd", .ops = &mov_ops, },
  136. { .name = "xadd", .ops = &mov_ops, },
  137. { .name = "xbeginl", .ops = &jump_ops, },
  138. { .name = "xbeginq", .ops = &jump_ops, },
  139. { .name = "xchg", .ops = &mov_ops, },
  140. { .name = "xor", .ops = &mov_ops, },
  141. { .name = "xorb", .ops = &mov_ops, },
  142. { .name = "xorpd", .ops = &mov_ops, },
  143. { .name = "xorps", .ops = &mov_ops, },
  144. };
  145. static bool x86__ins_is_fused(struct arch *arch, const char *ins1,
  146. const char *ins2)
  147. {
  148. if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
  149. return false;
  150. if (arch->model == 0x1e) {
  151. /* Nehalem */
  152. if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
  153. strstr(ins1, "test")) {
  154. return true;
  155. }
  156. } else {
  157. /* Newer platform */
  158. if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
  159. strstr(ins1, "test") ||
  160. strstr(ins1, "add") ||
  161. strstr(ins1, "sub") ||
  162. strstr(ins1, "and") ||
  163. strstr(ins1, "inc") ||
  164. strstr(ins1, "dec")) {
  165. return true;
  166. }
  167. }
  168. return false;
  169. }
  170. static int x86__cpuid_parse(struct arch *arch, char *cpuid)
  171. {
  172. unsigned int family, model, stepping;
  173. int ret;
  174. /*
  175. * cpuid = "GenuineIntel,family,model,stepping"
  176. */
  177. ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
  178. if (ret == 3) {
  179. arch->family = family;
  180. arch->model = model;
  181. return 0;
  182. }
  183. return -1;
  184. }
  185. static int x86__annotate_init(struct arch *arch, char *cpuid)
  186. {
  187. int err = 0;
  188. if (arch->initialized)
  189. return 0;
  190. if (cpuid)
  191. err = x86__cpuid_parse(arch, cpuid);
  192. arch->initialized = true;
  193. return err;
  194. }