00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "dis-asm.h"
00039 #include "sysdep.h"
00040 #include "opintl.h"
00041
00042 #define MAXLEN 20
00043
00044 #include <setjmp.h>
00045
00046 #ifndef UNIXWARE_COMPAT
00047
00048
00049 #define UNIXWARE_COMPAT 1
00050 #endif
00051
00052 static int fetch_data (struct disassemble_info *, bfd_byte *);
00053 static void ckprefix (void);
00054 static const char *prefix_name (int, int);
00055 static int print_insn (bfd_vma, disassemble_info *);
00056 static void dofloat (int);
00057 static void OP_ST (int, int);
00058 static void OP_STi (int, int);
00059 static int putop (const char *, int);
00060 static void oappend (const char *);
00061 static void append_seg (void);
00062 static void OP_indirE (int, int);
00063 static void print_operand_value (char *, int, bfd_vma);
00064 static void OP_E (int, int);
00065 static void OP_G (int, int);
00066 static bfd_vma get64 (void);
00067 static bfd_signed_vma get32 (void);
00068 static bfd_signed_vma get32s (void);
00069 static int get16 (void);
00070 static void set_op (bfd_vma, int);
00071 static void OP_REG (int, int);
00072 static void OP_IMREG (int, int);
00073 static void OP_I (int, int);
00074 static void OP_I64 (int, int);
00075 static void OP_sI (int, int);
00076 static void OP_J (int, int);
00077 static void OP_SEG (int, int);
00078 static void OP_DIR (int, int);
00079 static void OP_OFF (int, int);
00080 static void OP_OFF64 (int, int);
00081 static void ptr_reg (int, int);
00082 static void OP_ESreg (int, int);
00083 static void OP_DSreg (int, int);
00084 static void OP_C (int, int);
00085 static void OP_D (int, int);
00086 static void OP_T (int, int);
00087 static void OP_Rd (int, int);
00088 static void OP_MMX (int, int);
00089 static void OP_XMM (int, int);
00090 static void OP_EM (int, int);
00091 static void OP_EX (int, int);
00092 static void OP_MS (int, int);
00093 static void OP_XS (int, int);
00094 static void OP_M (int, int);
00095 static void OP_0fae (int, int);
00096 static void OP_0f07 (int, int);
00097 static void NOP_Fixup (int, int);
00098 static void OP_3DNowSuffix (int, int);
00099 static void OP_SIMD_Suffix (int, int);
00100 static void SIMD_Fixup (int, int);
00101 static void PNI_Fixup (int, int);
00102 static void INVLPG_Fixup (int, int);
00103 static void BadOp (void);
00104
00105 struct dis_private {
00106
00107 bfd_byte *max_fetched;
00108 bfd_byte the_buffer[MAXLEN];
00109 bfd_vma insn_start;
00110 int orig_sizeflag;
00111 jmp_buf bailout;
00112 };
00113
00114
00115
00116 #define FWAIT_OPCODE (0x9b)
00117
00118
00119 static int mode_64bit;
00120
00121
00122 static int prefixes;
00123
00124
00125 static int rex;
00126
00127 static int rex_used;
00128 #define REX_MODE64 8
00129 #define REX_EXTX 4
00130 #define REX_EXTY 2
00131 #define REX_EXTZ 1
00132
00133
00134
00135
00136 #define USED_REX(value) \
00137 { \
00138 if (value) \
00139 rex_used |= (rex & value) ? (value) | 0x40 : 0; \
00140 else \
00141 rex_used |= 0x40; \
00142 }
00143
00144
00145
00146 static int used_prefixes;
00147
00148
00149 #define PREFIX_REPZ 1
00150 #define PREFIX_REPNZ 2
00151 #define PREFIX_LOCK 4
00152 #define PREFIX_CS 8
00153 #define PREFIX_SS 0x10
00154 #define PREFIX_DS 0x20
00155 #define PREFIX_ES 0x40
00156 #define PREFIX_FS 0x80
00157 #define PREFIX_GS 0x100
00158 #define PREFIX_DATA 0x200
00159 #define PREFIX_ADDR 0x400
00160 #define PREFIX_FWAIT 0x800
00161
00162
00163
00164
00165 #define FETCH_DATA(info, addr) \
00166 ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \
00167 ? 1 : fetch_data ((info), (addr)))
00168
00169 static int
00170 fetch_data (struct disassemble_info *info, bfd_byte *addr)
00171 {
00172 int status;
00173 struct dis_private *priv = (struct dis_private *) info->private_data;
00174 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
00175
00176 status = (*info->read_memory_func) (start,
00177 priv->max_fetched,
00178 addr - priv->max_fetched,
00179 info);
00180 if (status != 0)
00181 {
00182
00183
00184
00185
00186 if (priv->max_fetched == priv->the_buffer)
00187 (*info->memory_error_func) (status, start, info);
00188 longjmp (priv->bailout, 1);
00189 }
00190 else
00191 priv->max_fetched = addr;
00192 return 1;
00193 }
00194
00195 #define XX NULL, 0
00196
00197 #define Eb OP_E, b_mode
00198 #define Ev OP_E, v_mode
00199 #define Ed OP_E, d_mode
00200 #define Eq OP_E, q_mode
00201 #define Edq OP_E, dq_mode
00202 #define Edqw OP_E, dqw_mode
00203 #define indirEv OP_indirE, v_mode
00204 #define indirEp OP_indirE, f_mode
00205 #define Ew OP_E, w_mode
00206 #define Ma OP_E, v_mode
00207 #define M OP_M, 0
00208 #define Mp OP_M, f_mode
00209 #define Gb OP_G, b_mode
00210 #define Gv OP_G, v_mode
00211 #define Gd OP_G, d_mode
00212 #define Gdq OP_G, dq_mode
00213 #define Gw OP_G, w_mode
00214 #define Rd OP_Rd, d_mode
00215 #define Rm OP_Rd, m_mode
00216 #define Ib OP_I, b_mode
00217 #define sIb OP_sI, b_mode
00218 #define Iv OP_I, v_mode
00219 #define Iq OP_I, q_mode
00220 #define Iv64 OP_I64, v_mode
00221 #define Iw OP_I, w_mode
00222 #define I1 OP_I, const_1_mode
00223 #define Jb OP_J, b_mode
00224 #define Jv OP_J, v_mode
00225 #define Cm OP_C, m_mode
00226 #define Dm OP_D, m_mode
00227 #define Td OP_T, d_mode
00228
00229 #define RMeAX OP_REG, eAX_reg
00230 #define RMeBX OP_REG, eBX_reg
00231 #define RMeCX OP_REG, eCX_reg
00232 #define RMeDX OP_REG, eDX_reg
00233 #define RMeSP OP_REG, eSP_reg
00234 #define RMeBP OP_REG, eBP_reg
00235 #define RMeSI OP_REG, eSI_reg
00236 #define RMeDI OP_REG, eDI_reg
00237 #define RMrAX OP_REG, rAX_reg
00238 #define RMrBX OP_REG, rBX_reg
00239 #define RMrCX OP_REG, rCX_reg
00240 #define RMrDX OP_REG, rDX_reg
00241 #define RMrSP OP_REG, rSP_reg
00242 #define RMrBP OP_REG, rBP_reg
00243 #define RMrSI OP_REG, rSI_reg
00244 #define RMrDI OP_REG, rDI_reg
00245 #define RMAL OP_REG, al_reg
00246 #define RMAL OP_REG, al_reg
00247 #define RMCL OP_REG, cl_reg
00248 #define RMDL OP_REG, dl_reg
00249 #define RMBL OP_REG, bl_reg
00250 #define RMAH OP_REG, ah_reg
00251 #define RMCH OP_REG, ch_reg
00252 #define RMDH OP_REG, dh_reg
00253 #define RMBH OP_REG, bh_reg
00254 #define RMAX OP_REG, ax_reg
00255 #define RMDX OP_REG, dx_reg
00256
00257 #define eAX OP_IMREG, eAX_reg
00258 #define eBX OP_IMREG, eBX_reg
00259 #define eCX OP_IMREG, eCX_reg
00260 #define eDX OP_IMREG, eDX_reg
00261 #define eSP OP_IMREG, eSP_reg
00262 #define eBP OP_IMREG, eBP_reg
00263 #define eSI OP_IMREG, eSI_reg
00264 #define eDI OP_IMREG, eDI_reg
00265 #define AL OP_IMREG, al_reg
00266 #define AL OP_IMREG, al_reg
00267 #define CL OP_IMREG, cl_reg
00268 #define DL OP_IMREG, dl_reg
00269 #define BL OP_IMREG, bl_reg
00270 #define AH OP_IMREG, ah_reg
00271 #define CH OP_IMREG, ch_reg
00272 #define DH OP_IMREG, dh_reg
00273 #define BH OP_IMREG, bh_reg
00274 #define AX OP_IMREG, ax_reg
00275 #define DX OP_IMREG, dx_reg
00276 #define indirDX OP_IMREG, indir_dx_reg
00277
00278 #define Sw OP_SEG, w_mode
00279 #define Ap OP_DIR, 0
00280 #define Ob OP_OFF, b_mode
00281 #define Ob64 OP_OFF64, b_mode
00282 #define Ov OP_OFF, v_mode
00283 #define Ov64 OP_OFF64, v_mode
00284 #define Xb OP_DSreg, eSI_reg
00285 #define Xv OP_DSreg, eSI_reg
00286 #define Yb OP_ESreg, eDI_reg
00287 #define Yv OP_ESreg, eDI_reg
00288 #define DSBX OP_DSreg, eBX_reg
00289
00290 #define es OP_REG, es_reg
00291 #define ss OP_REG, ss_reg
00292 #define cs OP_REG, cs_reg
00293 #define ds OP_REG, ds_reg
00294 #define fs OP_REG, fs_reg
00295 #define gs OP_REG, gs_reg
00296
00297 #define MX OP_MMX, 0
00298 #define XM OP_XMM, 0
00299 #define EM OP_EM, v_mode
00300 #define EX OP_EX, v_mode
00301 #define MS OP_MS, v_mode
00302 #define XS OP_XS, v_mode
00303 #define OPSUF OP_3DNowSuffix, 0
00304 #define OPSIMD OP_SIMD_Suffix, 0
00305
00306 #define cond_jump_flag NULL, cond_jump_mode
00307 #define loop_jcxz_flag NULL, loop_jcxz_mode
00308
00309
00310 #define SUFFIX_ALWAYS 4
00311 #define AFLAG 2
00312 #define DFLAG 1
00313
00314 #define b_mode 1
00315 #define v_mode 2
00316 #define w_mode 3
00317 #define d_mode 4
00318 #define q_mode 5
00319 #define t_mode 6
00320 #define x_mode 7
00321 #define m_mode 8
00322 #define cond_jump_mode 9
00323 #define loop_jcxz_mode 10
00324 #define dq_mode 11
00325 #define dqw_mode 12
00326 #define f_mode 13
00327 #define const_1_mode 14
00328
00329 #define es_reg 100
00330 #define cs_reg 101
00331 #define ss_reg 102
00332 #define ds_reg 103
00333 #define fs_reg 104
00334 #define gs_reg 105
00335
00336 #define eAX_reg 108
00337 #define eCX_reg 109
00338 #define eDX_reg 110
00339 #define eBX_reg 111
00340 #define eSP_reg 112
00341 #define eBP_reg 113
00342 #define eSI_reg 114
00343 #define eDI_reg 115
00344
00345 #define al_reg 116
00346 #define cl_reg 117
00347 #define dl_reg 118
00348 #define bl_reg 119
00349 #define ah_reg 120
00350 #define ch_reg 121
00351 #define dh_reg 122
00352 #define bh_reg 123
00353
00354 #define ax_reg 124
00355 #define cx_reg 125
00356 #define dx_reg 126
00357 #define bx_reg 127
00358 #define sp_reg 128
00359 #define bp_reg 129
00360 #define si_reg 130
00361 #define di_reg 131
00362
00363 #define rAX_reg 132
00364 #define rCX_reg 133
00365 #define rDX_reg 134
00366 #define rBX_reg 135
00367 #define rSP_reg 136
00368 #define rBP_reg 137
00369 #define rSI_reg 138
00370 #define rDI_reg 139
00371
00372 #define indir_dx_reg 150
00373
00374 #define FLOATCODE 1
00375 #define USE_GROUPS 2
00376 #define USE_PREFIX_USER_TABLE 3
00377 #define X86_64_SPECIAL 4
00378
00379 #define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
00380
00381 #define GRP1b NULL, NULL, USE_GROUPS, NULL, 0, NULL, 0
00382 #define GRP1S NULL, NULL, USE_GROUPS, NULL, 1, NULL, 0
00383 #define GRP1Ss NULL, NULL, USE_GROUPS, NULL, 2, NULL, 0
00384 #define GRP2b NULL, NULL, USE_GROUPS, NULL, 3, NULL, 0
00385 #define GRP2S NULL, NULL, USE_GROUPS, NULL, 4, NULL, 0
00386 #define GRP2b_one NULL, NULL, USE_GROUPS, NULL, 5, NULL, 0
00387 #define GRP2S_one NULL, NULL, USE_GROUPS, NULL, 6, NULL, 0
00388 #define GRP2b_cl NULL, NULL, USE_GROUPS, NULL, 7, NULL, 0
00389 #define GRP2S_cl NULL, NULL, USE_GROUPS, NULL, 8, NULL, 0
00390 #define GRP3b NULL, NULL, USE_GROUPS, NULL, 9, NULL, 0
00391 #define GRP3S NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0
00392 #define GRP4 NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0
00393 #define GRP5 NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0
00394 #define GRP6 NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0
00395 #define GRP7 NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0
00396 #define GRP8 NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0
00397 #define GRP9 NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0
00398 #define GRP10 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0
00399 #define GRP11 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0
00400 #define GRP12 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0
00401 #define GRP13 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0
00402 #define GRP14 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0
00403 #define GRPAMD NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0
00404 #define GRPPADLCK1 NULL, NULL, USE_GROUPS, NULL, 23, NULL, 0
00405 #define GRPPADLCK2 NULL, NULL, USE_GROUPS, NULL, 24, NULL, 0
00406
00407 #define PREGRP0 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 0, NULL, 0
00408 #define PREGRP1 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 1, NULL, 0
00409 #define PREGRP2 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 2, NULL, 0
00410 #define PREGRP3 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 3, NULL, 0
00411 #define PREGRP4 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 4, NULL, 0
00412 #define PREGRP5 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 5, NULL, 0
00413 #define PREGRP6 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 6, NULL, 0
00414 #define PREGRP7 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 7, NULL, 0
00415 #define PREGRP8 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 8, NULL, 0
00416 #define PREGRP9 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 9, NULL, 0
00417 #define PREGRP10 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0
00418 #define PREGRP11 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0
00419 #define PREGRP12 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0
00420 #define PREGRP13 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0
00421 #define PREGRP14 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0
00422 #define PREGRP15 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0
00423 #define PREGRP16 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0
00424 #define PREGRP17 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0
00425 #define PREGRP18 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0
00426 #define PREGRP19 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0
00427 #define PREGRP20 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0
00428 #define PREGRP21 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0
00429 #define PREGRP22 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0
00430 #define PREGRP23 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0
00431 #define PREGRP24 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0
00432 #define PREGRP25 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0
00433 #define PREGRP26 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0
00434 #define PREGRP27 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 27, NULL, 0
00435 #define PREGRP28 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 28, NULL, 0
00436 #define PREGRP29 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 29, NULL, 0
00437 #define PREGRP30 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 30, NULL, 0
00438 #define PREGRP31 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 31, NULL, 0
00439 #define PREGRP32 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 32, NULL, 0
00440
00441 #define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0
00442
00443 typedef void (*op_rtn) (int bytemode, int sizeflag);
00444
00445 struct dis386 {
00446 const char *name;
00447 op_rtn op1;
00448 int bytemode1;
00449 op_rtn op2;
00450 int bytemode2;
00451 op_rtn op3;
00452 int bytemode3;
00453 };
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 static const struct dis386 dis386[] = {
00491
00492 { "addB", Eb, Gb, XX },
00493 { "addS", Ev, Gv, XX },
00494 { "addB", Gb, Eb, XX },
00495 { "addS", Gv, Ev, XX },
00496 { "addB", AL, Ib, XX },
00497 { "addS", eAX, Iv, XX },
00498 { "push{T|}", es, XX, XX },
00499 { "pop{T|}", es, XX, XX },
00500
00501 { "orB", Eb, Gb, XX },
00502 { "orS", Ev, Gv, XX },
00503 { "orB", Gb, Eb, XX },
00504 { "orS", Gv, Ev, XX },
00505 { "orB", AL, Ib, XX },
00506 { "orS", eAX, Iv, XX },
00507 { "push{T|}", cs, XX, XX },
00508 { "(bad)", XX, XX, XX },
00509
00510 { "adcB", Eb, Gb, XX },
00511 { "adcS", Ev, Gv, XX },
00512 { "adcB", Gb, Eb, XX },
00513 { "adcS", Gv, Ev, XX },
00514 { "adcB", AL, Ib, XX },
00515 { "adcS", eAX, Iv, XX },
00516 { "push{T|}", ss, XX, XX },
00517 { "popT|}", ss, XX, XX },
00518
00519 { "sbbB", Eb, Gb, XX },
00520 { "sbbS", Ev, Gv, XX },
00521 { "sbbB", Gb, Eb, XX },
00522 { "sbbS", Gv, Ev, XX },
00523 { "sbbB", AL, Ib, XX },
00524 { "sbbS", eAX, Iv, XX },
00525 { "push{T|}", ds, XX, XX },
00526 { "pop{T|}", ds, XX, XX },
00527
00528 { "andB", Eb, Gb, XX },
00529 { "andS", Ev, Gv, XX },
00530 { "andB", Gb, Eb, XX },
00531 { "andS", Gv, Ev, XX },
00532 { "andB", AL, Ib, XX },
00533 { "andS", eAX, Iv, XX },
00534 { "(bad)", XX, XX, XX },
00535 { "daa{|}", XX, XX, XX },
00536
00537 { "subB", Eb, Gb, XX },
00538 { "subS", Ev, Gv, XX },
00539 { "subB", Gb, Eb, XX },
00540 { "subS", Gv, Ev, XX },
00541 { "subB", AL, Ib, XX },
00542 { "subS", eAX, Iv, XX },
00543 { "(bad)", XX, XX, XX },
00544 { "das{|}", XX, XX, XX },
00545
00546 { "xorB", Eb, Gb, XX },
00547 { "xorS", Ev, Gv, XX },
00548 { "xorB", Gb, Eb, XX },
00549 { "xorS", Gv, Ev, XX },
00550 { "xorB", AL, Ib, XX },
00551 { "xorS", eAX, Iv, XX },
00552 { "(bad)", XX, XX, XX },
00553 { "aaa{|}", XX, XX, XX },
00554
00555 { "cmpB", Eb, Gb, XX },
00556 { "cmpS", Ev, Gv, XX },
00557 { "cmpB", Gb, Eb, XX },
00558 { "cmpS", Gv, Ev, XX },
00559 { "cmpB", AL, Ib, XX },
00560 { "cmpS", eAX, Iv, XX },
00561 { "(bad)", XX, XX, XX },
00562 { "aas{|}", XX, XX, XX },
00563
00564 { "inc{S|}", RMeAX, XX, XX },
00565 { "inc{S|}", RMeCX, XX, XX },
00566 { "inc{S|}", RMeDX, XX, XX },
00567 { "inc{S|}", RMeBX, XX, XX },
00568 { "inc{S|}", RMeSP, XX, XX },
00569 { "inc{S|}", RMeBP, XX, XX },
00570 { "inc{S|}", RMeSI, XX, XX },
00571 { "inc{S|}", RMeDI, XX, XX },
00572
00573 { "dec{S|}", RMeAX, XX, XX },
00574 { "dec{S|}", RMeCX, XX, XX },
00575 { "dec{S|}", RMeDX, XX, XX },
00576 { "dec{S|}", RMeBX, XX, XX },
00577 { "dec{S|}", RMeSP, XX, XX },
00578 { "dec{S|}", RMeBP, XX, XX },
00579 { "dec{S|}", RMeSI, XX, XX },
00580 { "dec{S|}", RMeDI, XX, XX },
00581
00582 { "pushS", RMrAX, XX, XX },
00583 { "pushS", RMrCX, XX, XX },
00584 { "pushS", RMrDX, XX, XX },
00585 { "pushS", RMrBX, XX, XX },
00586 { "pushS", RMrSP, XX, XX },
00587 { "pushS", RMrBP, XX, XX },
00588 { "pushS", RMrSI, XX, XX },
00589 { "pushS", RMrDI, XX, XX },
00590
00591 { "popS", RMrAX, XX, XX },
00592 { "popS", RMrCX, XX, XX },
00593 { "popS", RMrDX, XX, XX },
00594 { "popS", RMrBX, XX, XX },
00595 { "popS", RMrSP, XX, XX },
00596 { "popS", RMrBP, XX, XX },
00597 { "popS", RMrSI, XX, XX },
00598 { "popS", RMrDI, XX, XX },
00599
00600 { "pusha{P|}", XX, XX, XX },
00601 { "popa{P|}", XX, XX, XX },
00602 { "bound{S|}", Gv, Ma, XX },
00603 { X86_64_0 },
00604 { "(bad)", XX, XX, XX },
00605 { "(bad)", XX, XX, XX },
00606 { "(bad)", XX, XX, XX },
00607 { "(bad)", XX, XX, XX },
00608
00609 { "pushT", Iq, XX, XX },
00610 { "imulS", Gv, Ev, Iv },
00611 { "pushT", sIb, XX, XX },
00612 { "imulS", Gv, Ev, sIb },
00613 { "ins{b||b|}", Yb, indirDX, XX },
00614 { "ins{R||R|}", Yv, indirDX, XX },
00615 { "outs{b||b|}", indirDX, Xb, XX },
00616 { "outs{R||R|}", indirDX, Xv, XX },
00617
00618 { "joH", Jb, XX, cond_jump_flag },
00619 { "jnoH", Jb, XX, cond_jump_flag },
00620 { "jbH", Jb, XX, cond_jump_flag },
00621 { "jaeH", Jb, XX, cond_jump_flag },
00622 { "jeH", Jb, XX, cond_jump_flag },
00623 { "jneH", Jb, XX, cond_jump_flag },
00624 { "jbeH", Jb, XX, cond_jump_flag },
00625 { "jaH", Jb, XX, cond_jump_flag },
00626
00627 { "jsH", Jb, XX, cond_jump_flag },
00628 { "jnsH", Jb, XX, cond_jump_flag },
00629 { "jpH", Jb, XX, cond_jump_flag },
00630 { "jnpH", Jb, XX, cond_jump_flag },
00631 { "jlH", Jb, XX, cond_jump_flag },
00632 { "jgeH", Jb, XX, cond_jump_flag },
00633 { "jleH", Jb, XX, cond_jump_flag },
00634 { "jgH", Jb, XX, cond_jump_flag },
00635
00636 { GRP1b },
00637 { GRP1S },
00638 { "(bad)", XX, XX, XX },
00639 { GRP1Ss },
00640 { "testB", Eb, Gb, XX },
00641 { "testS", Ev, Gv, XX },
00642 { "xchgB", Eb, Gb, XX },
00643 { "xchgS", Ev, Gv, XX },
00644
00645 { "movB", Eb, Gb, XX },
00646 { "movS", Ev, Gv, XX },
00647 { "movB", Gb, Eb, XX },
00648 { "movS", Gv, Ev, XX },
00649 { "movQ", Ev, Sw, XX },
00650 { "leaS", Gv, M, XX },
00651 { "movQ", Sw, Ev, XX },
00652 { "popU", Ev, XX, XX },
00653
00654 { "nop", NOP_Fixup, 0, XX, XX },
00655 { "xchgS", RMeCX, eAX, XX },
00656 { "xchgS", RMeDX, eAX, XX },
00657 { "xchgS", RMeBX, eAX, XX },
00658 { "xchgS", RMeSP, eAX, XX },
00659 { "xchgS", RMeBP, eAX, XX },
00660 { "xchgS", RMeSI, eAX, XX },
00661 { "xchgS", RMeDI, eAX, XX },
00662
00663 { "cW{tR||tR|}", XX, XX, XX },
00664 { "cR{tO||tO|}", XX, XX, XX },
00665 { "Jcall{T|}", Ap, XX, XX },
00666 { "(bad)", XX, XX, XX },
00667 { "pushfT", XX, XX, XX },
00668 { "popfT", XX, XX, XX },
00669 { "sahf{|}", XX, XX, XX },
00670 { "lahf{|}", XX, XX, XX },
00671
00672 { "movB", AL, Ob64, XX },
00673 { "movS", eAX, Ov64, XX },
00674 { "movB", Ob64, AL, XX },
00675 { "movS", Ov64, eAX, XX },
00676 { "movs{b||b|}", Yb, Xb, XX },
00677 { "movs{R||R|}", Yv, Xv, XX },
00678 { "cmps{b||b|}", Xb, Yb, XX },
00679 { "cmps{R||R|}", Xv, Yv, XX },
00680
00681 { "testB", AL, Ib, XX },
00682 { "testS", eAX, Iv, XX },
00683 { "stosB", Yb, AL, XX },
00684 { "stosS", Yv, eAX, XX },
00685 { "lodsB", AL, Xb, XX },
00686 { "lodsS", eAX, Xv, XX },
00687 { "scasB", AL, Yb, XX },
00688 { "scasS", eAX, Yv, XX },
00689
00690 { "movB", RMAL, Ib, XX },
00691 { "movB", RMCL, Ib, XX },
00692 { "movB", RMDL, Ib, XX },
00693 { "movB", RMBL, Ib, XX },
00694 { "movB", RMAH, Ib, XX },
00695 { "movB", RMCH, Ib, XX },
00696 { "movB", RMDH, Ib, XX },
00697 { "movB", RMBH, Ib, XX },
00698
00699 { "movS", RMeAX, Iv64, XX },
00700 { "movS", RMeCX, Iv64, XX },
00701 { "movS", RMeDX, Iv64, XX },
00702 { "movS", RMeBX, Iv64, XX },
00703 { "movS", RMeSP, Iv64, XX },
00704 { "movS", RMeBP, Iv64, XX },
00705 { "movS", RMeSI, Iv64, XX },
00706 { "movS", RMeDI, Iv64, XX },
00707
00708 { GRP2b },
00709 { GRP2S },
00710 { "retT", Iw, XX, XX },
00711 { "retT", XX, XX, XX },
00712 { "les{S|}", Gv, Mp, XX },
00713 { "ldsS", Gv, Mp, XX },
00714 { "movA", Eb, Ib, XX },
00715 { "movQ", Ev, Iv, XX },
00716
00717 { "enterT", Iw, Ib, XX },
00718 { "leaveT", XX, XX, XX },
00719 { "lretP", Iw, XX, XX },
00720 { "lretP", XX, XX, XX },
00721 { "int3", XX, XX, XX },
00722 { "int", Ib, XX, XX },
00723 { "into{|}", XX, XX, XX },
00724 { "iretP", XX, XX, XX },
00725
00726 { GRP2b_one },
00727 { GRP2S_one },
00728 { GRP2b_cl },
00729 { GRP2S_cl },
00730 { "aam{|}", sIb, XX, XX },
00731 { "aad{|}", sIb, XX, XX },
00732 { "(bad)", XX, XX, XX },
00733 { "xlat", DSBX, XX, XX },
00734
00735 { FLOAT },
00736 { FLOAT },
00737 { FLOAT },
00738 { FLOAT },
00739 { FLOAT },
00740 { FLOAT },
00741 { FLOAT },
00742 { FLOAT },
00743
00744 { "loopneFH", Jb, XX, loop_jcxz_flag },
00745 { "loopeFH", Jb, XX, loop_jcxz_flag },
00746 { "loopFH", Jb, XX, loop_jcxz_flag },
00747 { "jEcxzH", Jb, XX, loop_jcxz_flag },
00748 { "inB", AL, Ib, XX },
00749 { "inS", eAX, Ib, XX },
00750 { "outB", Ib, AL, XX },
00751 { "outS", Ib, eAX, XX },
00752
00753 { "callT", Jv, XX, XX },
00754 { "jmpT", Jv, XX, XX },
00755 { "Jjmp{T|}", Ap, XX, XX },
00756 { "jmp", Jb, XX, XX },
00757 { "inB", AL, indirDX, XX },
00758 { "inS", eAX, indirDX, XX },
00759 { "outB", indirDX, AL, XX },
00760 { "outS", indirDX, eAX, XX },
00761
00762 { "(bad)", XX, XX, XX },
00763 { "icebp", XX, XX, XX },
00764 { "(bad)", XX, XX, XX },
00765 { "(bad)", XX, XX, XX },
00766 { "hlt", XX, XX, XX },
00767 { "cmc", XX, XX, XX },
00768 { GRP3b },
00769 { GRP3S },
00770
00771 { "clc", XX, XX, XX },
00772 { "stc", XX, XX, XX },
00773 { "cli", XX, XX, XX },
00774 { "sti", XX, XX, XX },
00775 { "cld", XX, XX, XX },
00776 { "std", XX, XX, XX },
00777 { GRP4 },
00778 { GRP5 },
00779 };
00780
00781 static const struct dis386 dis386_twobyte[] = {
00782
00783 { GRP6 },
00784 { GRP7 },
00785 { "larS", Gv, Ew, XX },
00786 { "lslS", Gv, Ew, XX },
00787 { "(bad)", XX, XX, XX },
00788 { "syscall", XX, XX, XX },
00789 { "clts", XX, XX, XX },
00790 { "sysretP", XX, XX, XX },
00791
00792 { "invd", XX, XX, XX },
00793 { "wbinvd", XX, XX, XX },
00794 { "(bad)", XX, XX, XX },
00795 { "ud2a", XX, XX, XX },
00796 { "(bad)", XX, XX, XX },
00797 { GRPAMD },
00798 { "femms", XX, XX, XX },
00799 { "", MX, EM, OPSUF },
00800
00801 { PREGRP8 },
00802 { PREGRP9 },
00803 { PREGRP30 },
00804 { "movlpX", EX, XM, SIMD_Fixup, 'h' },
00805 { "unpcklpX", XM, EX, XX },
00806 { "unpckhpX", XM, EX, XX },
00807 { PREGRP31 },
00808 { "movhpX", EX, XM, SIMD_Fixup, 'l' },
00809
00810 { GRP14 },
00811 { "(bad)", XX, XX, XX },
00812 { "(bad)", XX, XX, XX },
00813 { "(bad)", XX, XX, XX },
00814 { "(bad)", XX, XX, XX },
00815 { "(bad)", XX, XX, XX },
00816 { "(bad)", XX, XX, XX },
00817 { "(bad)", XX, XX, XX },
00818
00819 { "movL", Rm, Cm, XX },
00820 { "movL", Rm, Dm, XX },
00821 { "movL", Cm, Rm, XX },
00822 { "movL", Dm, Rm, XX },
00823 { "movL", Rd, Td, XX },
00824 { "(bad)", XX, XX, XX },
00825 { "movL", Td, Rd, XX },
00826 { "(bad)", XX, XX, XX },
00827
00828 { "movapX", XM, EX, XX },
00829 { "movapX", EX, XM, XX },
00830 { PREGRP2 },
00831 { "movntpX", Ev, XM, XX },
00832 { PREGRP4 },
00833 { PREGRP3 },
00834 { "ucomisX", XM,EX, XX },
00835 { "comisX", XM,EX, XX },
00836
00837 { "wrmsr", XX, XX, XX },
00838 { "rdtsc", XX, XX, XX },
00839 { "rdmsr", XX, XX, XX },
00840 { "rdpmc", XX, XX, XX },
00841 { "sysenter", XX, XX, XX },
00842 { "sysexit", XX, XX, XX },
00843 { "(bad)", XX, XX, XX },
00844 { "(bad)", XX, XX, XX },
00845
00846 { "(bad)", XX, XX, XX },
00847 { "(bad)", XX, XX, XX },
00848 { "(bad)", XX, XX, XX },
00849 { "(bad)", XX, XX, XX },
00850 { "(bad)", XX, XX, XX },
00851 { "(bad)", XX, XX, XX },
00852 { "(bad)", XX, XX, XX },
00853 { "(bad)", XX, XX, XX },
00854
00855 { "cmovo", Gv, Ev, XX },
00856 { "cmovno", Gv, Ev, XX },
00857 { "cmovb", Gv, Ev, XX },
00858 { "cmovae", Gv, Ev, XX },
00859 { "cmove", Gv, Ev, XX },
00860 { "cmovne", Gv, Ev, XX },
00861 { "cmovbe", Gv, Ev, XX },
00862 { "cmova", Gv, Ev, XX },
00863
00864 { "cmovs", Gv, Ev, XX },
00865 { "cmovns", Gv, Ev, XX },
00866 { "cmovp", Gv, Ev, XX },
00867 { "cmovnp", Gv, Ev, XX },
00868 { "cmovl", Gv, Ev, XX },
00869 { "cmovge", Gv, Ev, XX },
00870 { "cmovle", Gv, Ev, XX },
00871 { "cmovg", Gv, Ev, XX },
00872
00873 { "movmskpX", Gdq, XS, XX },
00874 { PREGRP13 },
00875 { PREGRP12 },
00876 { PREGRP11 },
00877 { "andpX", XM, EX, XX },
00878 { "andnpX", XM, EX, XX },
00879 { "orpX", XM, EX, XX },
00880 { "xorpX", XM, EX, XX },
00881
00882 { PREGRP0 },
00883 { PREGRP10 },
00884 { PREGRP17 },
00885 { PREGRP16 },
00886 { PREGRP14 },
00887 { PREGRP7 },
00888 { PREGRP5 },
00889 { PREGRP6 },
00890
00891 { "punpcklbw", MX, EM, XX },
00892 { "punpcklwd", MX, EM, XX },
00893 { "punpckldq", MX, EM, XX },
00894 { "packsswb", MX, EM, XX },
00895 { "pcmpgtb", MX, EM, XX },
00896 { "pcmpgtw", MX, EM, XX },
00897 { "pcmpgtd", MX, EM, XX },
00898 { "packuswb", MX, EM, XX },
00899
00900 { "punpckhbw", MX, EM, XX },
00901 { "punpckhwd", MX, EM, XX },
00902 { "punpckhdq", MX, EM, XX },
00903 { "packssdw", MX, EM, XX },
00904 { PREGRP26 },
00905 { PREGRP24 },
00906 { "movd", MX, Edq, XX },
00907 { PREGRP19 },
00908
00909 { PREGRP22 },
00910 { GRP10 },
00911 { GRP11 },
00912 { GRP12 },
00913 { "pcmpeqb", MX, EM, XX },
00914 { "pcmpeqw", MX, EM, XX },
00915 { "pcmpeqd", MX, EM, XX },
00916 { "emms", XX, XX, XX },
00917
00918 { "(bad)", XX, XX, XX },
00919 { "(bad)", XX, XX, XX },
00920 { "(bad)", XX, XX, XX },
00921 { "(bad)", XX, XX, XX },
00922 { PREGRP28 },
00923 { PREGRP29 },
00924 { PREGRP23 },
00925 { PREGRP20 },
00926
00927 { "joH", Jv, XX, cond_jump_flag },
00928 { "jnoH", Jv, XX, cond_jump_flag },
00929 { "jbH", Jv, XX, cond_jump_flag },
00930 { "jaeH", Jv, XX, cond_jump_flag },
00931 { "jeH", Jv, XX, cond_jump_flag },
00932 { "jneH", Jv, XX, cond_jump_flag },
00933 { "jbeH", Jv, XX, cond_jump_flag },
00934 { "jaH", Jv, XX, cond_jump_flag },
00935
00936 { "jsH", Jv, XX, cond_jump_flag },
00937 { "jnsH", Jv, XX, cond_jump_flag },
00938 { "jpH", Jv, XX, cond_jump_flag },
00939 { "jnpH", Jv, XX, cond_jump_flag },
00940 { "jlH", Jv, XX, cond_jump_flag },
00941 { "jgeH", Jv, XX, cond_jump_flag },
00942 { "jleH", Jv, XX, cond_jump_flag },
00943 { "jgH", Jv, XX, cond_jump_flag },
00944
00945 { "seto", Eb, XX, XX },
00946 { "setno", Eb, XX, XX },
00947 { "setb", Eb, XX, XX },
00948 { "setae", Eb, XX, XX },
00949 { "sete", Eb, XX, XX },
00950 { "setne", Eb, XX, XX },
00951 { "setbe", Eb, XX, XX },
00952 { "seta", Eb, XX, XX },
00953
00954 { "sets", Eb, XX, XX },
00955 { "setns", Eb, XX, XX },
00956 { "setp", Eb, XX, XX },
00957 { "setnp", Eb, XX, XX },
00958 { "setl", Eb, XX, XX },
00959 { "setge", Eb, XX, XX },
00960 { "setle", Eb, XX, XX },
00961 { "setg", Eb, XX, XX },
00962
00963 { "pushT", fs, XX, XX },
00964 { "popT", fs, XX, XX },
00965 { "cpuid", XX, XX, XX },
00966 { "btS", Ev, Gv, XX },
00967 { "shldS", Ev, Gv, Ib },
00968 { "shldS", Ev, Gv, CL },
00969 { GRPPADLCK2 },
00970 { GRPPADLCK1 },
00971
00972 { "pushT", gs, XX, XX },
00973 { "popT", gs, XX, XX },
00974 { "rsm", XX, XX, XX },
00975 { "btsS", Ev, Gv, XX },
00976 { "shrdS", Ev, Gv, Ib },
00977 { "shrdS", Ev, Gv, CL },
00978 { GRP13 },
00979 { "imulS", Gv, Ev, XX },
00980
00981 { "cmpxchgB", Eb, Gb, XX },
00982 { "cmpxchgS", Ev, Gv, XX },
00983 { "lssS", Gv, Mp, XX },
00984 { "btrS", Ev, Gv, XX },
00985 { "lfsS", Gv, Mp, XX },
00986 { "lgsS", Gv, Mp, XX },
00987 { "movz{bR|x|bR|x}", Gv, Eb, XX },
00988 { "movz{wR|x|wR|x}", Gv, Ew, XX },
00989
00990 { "(bad)", XX, XX, XX },
00991 { "ud2b", XX, XX, XX },
00992 { GRP8 },
00993 { "btcS", Ev, Gv, XX },
00994 { "bsfS", Gv, Ev, XX },
00995 { "bsrS", Gv, Ev, XX },
00996 { "movs{bR|x|bR|x}", Gv, Eb, XX },
00997 { "movs{wR|x|wR|x}", Gv, Ew, XX },
00998
00999 { "xaddB", Eb, Gb, XX },
01000 { "xaddS", Ev, Gv, XX },
01001 { PREGRP1 },
01002 { "movntiS", Ev, Gv, XX },
01003 { "pinsrw", MX, Edqw, Ib },
01004 { "pextrw", Gdq, MS, Ib },
01005 { "shufpX", XM, EX, Ib },
01006 { GRP9 },
01007
01008 { "bswap", RMeAX, XX, XX },
01009 { "bswap", RMeCX, XX, XX },
01010 { "bswap", RMeDX, XX, XX },
01011 { "bswap", RMeBX, XX, XX },
01012 { "bswap", RMeSP, XX, XX },
01013 { "bswap", RMeBP, XX, XX },
01014 { "bswap", RMeSI, XX, XX },
01015 { "bswap", RMeDI, XX, XX },
01016
01017 { PREGRP27 },
01018 { "psrlw", MX, EM, XX },
01019 { "psrld", MX, EM, XX },
01020 { "psrlq", MX, EM, XX },
01021 { "paddq", MX, EM, XX },
01022 { "pmullw", MX, EM, XX },
01023 { PREGRP21 },
01024 { "pmovmskb", Gdq, MS, XX },
01025
01026 { "psubusb", MX, EM, XX },
01027 { "psubusw", MX, EM, XX },
01028 { "pminub", MX, EM, XX },
01029 { "pand", MX, EM, XX },
01030 { "paddusb", MX, EM, XX },
01031 { "paddusw", MX, EM, XX },
01032 { "pmaxub", MX, EM, XX },
01033 { "pandn", MX, EM, XX },
01034
01035 { "pavgb", MX, EM, XX },
01036 { "psraw", MX, EM, XX },
01037 { "psrad", MX, EM, XX },
01038 { "pavgw", MX, EM, XX },
01039 { "pmulhuw", MX, EM, XX },
01040 { "pmulhw", MX, EM, XX },
01041 { PREGRP15 },
01042 { PREGRP25 },
01043
01044 { "psubsb", MX, EM, XX },
01045 { "psubsw", MX, EM, XX },
01046 { "pminsw", MX, EM, XX },
01047 { "por", MX, EM, XX },
01048 { "paddsb", MX, EM, XX },
01049 { "paddsw", MX, EM, XX },
01050 { "pmaxsw", MX, EM, XX },
01051 { "pxor", MX, EM, XX },
01052
01053 { PREGRP32 },
01054 { "psllw", MX, EM, XX },
01055 { "pslld", MX, EM, XX },
01056 { "psllq", MX, EM, XX },
01057 { "pmuludq", MX, EM, XX },
01058 { "pmaddwd", MX, EM, XX },
01059 { "psadbw", MX, EM, XX },
01060 { PREGRP18 },
01061
01062 { "psubb", MX, EM, XX },
01063 { "psubw", MX, EM, XX },
01064 { "psubd", MX, EM, XX },
01065 { "psubq", MX, EM, XX },
01066 { "paddb", MX, EM, XX },
01067 { "paddw", MX, EM, XX },
01068 { "paddd", MX, EM, XX },
01069 { "(bad)", XX, XX, XX }
01070 };
01071
01072 static const unsigned char onebyte_has_modrm[256] = {
01073
01074
01075 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
01076 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
01077 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
01078 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
01079 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01080 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01081 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
01082 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01083 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
01084 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01085 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01086 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01087 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
01088 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
01089 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01090 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1
01091
01092
01093 };
01094
01095 static const unsigned char twobyte_has_modrm[256] = {
01096
01097
01098 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1,
01099 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
01100 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,
01101 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01102 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
01103 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
01104 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
01105 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,
01106 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01107 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
01108 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,
01109 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,
01110 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
01111 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
01112 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
01113 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
01114
01115
01116 };
01117
01118 static const unsigned char twobyte_uses_SSE_prefix[256] = {
01119
01120
01121 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01122 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,
01123 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,
01124 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01125 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01126 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
01127 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,
01128 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,
01129 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01130 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01131 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01132 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
01133 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
01134 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
01135 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
01136 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0
01137
01138
01139 };
01140
01141 static char obuf[100];
01142 static char *obufp;
01143 static char scratchbuf[100];
01144 static unsigned char *start_codep;
01145 static unsigned char *insn_codep;
01146 static unsigned char *codep;
01147 static disassemble_info *the_info;
01148 static int mod;
01149 static int rm;
01150 static int reg;
01151 static unsigned char need_modrm;
01152
01153
01154
01155
01156 #define MODRM_CHECK if (!need_modrm) abort ()
01157
01158 static const char **names64;
01159 static const char **names32;
01160 static const char **names16;
01161 static const char **names8;
01162 static const char **names8rex;
01163 static const char **names_seg;
01164 static const char **index16;
01165
01166 static const char *intel_names64[] = {
01167 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
01168 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
01169 };
01170 static const char *intel_names32[] = {
01171 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
01172 "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
01173 };
01174 static const char *intel_names16[] = {
01175 "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
01176 "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
01177 };
01178 static const char *intel_names8[] = {
01179 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
01180 };
01181 static const char *intel_names8rex[] = {
01182 "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
01183 "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
01184 };
01185 static const char *intel_names_seg[] = {
01186 "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
01187 };
01188 static const char *intel_index16[] = {
01189 "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
01190 };
01191
01192 static const char *att_names64[] = {
01193 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
01194 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
01195 };
01196 static const char *att_names32[] = {
01197 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
01198 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
01199 };
01200 static const char *att_names16[] = {
01201 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
01202 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
01203 };
01204 static const char *att_names8[] = {
01205 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
01206 };
01207 static const char *att_names8rex[] = {
01208 "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
01209 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
01210 };
01211 static const char *att_names_seg[] = {
01212 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
01213 };
01214 static const char *att_index16[] = {
01215 "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
01216 };
01217
01218 static const struct dis386 grps[][8] = {
01219
01220 {
01221 { "addA", Eb, Ib, XX },
01222 { "orA", Eb, Ib, XX },
01223 { "adcA", Eb, Ib, XX },
01224 { "sbbA", Eb, Ib, XX },
01225 { "andA", Eb, Ib, XX },
01226 { "subA", Eb, Ib, XX },
01227 { "xorA", Eb, Ib, XX },
01228 { "cmpA", Eb, Ib, XX }
01229 },
01230
01231 {
01232 { "addQ", Ev, Iv, XX },
01233 { "orQ", Ev, Iv, XX },
01234 { "adcQ", Ev, Iv, XX },
01235 { "sbbQ", Ev, Iv, XX },
01236 { "andQ", Ev, Iv, XX },
01237 { "subQ", Ev, Iv, XX },
01238 { "xorQ", Ev, Iv, XX },
01239 { "cmpQ", Ev, Iv, XX }
01240 },
01241
01242 {
01243 { "addQ", Ev, sIb, XX },
01244 { "orQ", Ev, sIb, XX },
01245 { "adcQ", Ev, sIb, XX },
01246 { "sbbQ", Ev, sIb, XX },
01247 { "andQ", Ev, sIb, XX },
01248 { "subQ", Ev, sIb, XX },
01249 { "xorQ", Ev, sIb, XX },
01250 { "cmpQ", Ev, sIb, XX }
01251 },
01252
01253 {
01254 { "rolA", Eb, Ib, XX },
01255 { "rorA", Eb, Ib, XX },
01256 { "rclA", Eb, Ib, XX },
01257 { "rcrA", Eb, Ib, XX },
01258 { "shlA", Eb, Ib, XX },
01259 { "shrA", Eb, Ib, XX },
01260 { "(bad)", XX, XX, XX },
01261 { "sarA", Eb, Ib, XX },
01262 },
01263
01264 {
01265 { "rolQ", Ev, Ib, XX },
01266 { "rorQ", Ev, Ib, XX },
01267 { "rclQ", Ev, Ib, XX },
01268 { "rcrQ", Ev, Ib, XX },
01269 { "shlQ", Ev, Ib, XX },
01270 { "shrQ", Ev, Ib, XX },
01271 { "(bad)", XX, XX, XX },
01272 { "sarQ", Ev, Ib, XX },
01273 },
01274
01275 {
01276 { "rolA", Eb, I1, XX },
01277 { "rorA", Eb, I1, XX },
01278 { "rclA", Eb, I1, XX },
01279 { "rcrA", Eb, I1, XX },
01280 { "shlA", Eb, I1, XX },
01281 { "shrA", Eb, I1, XX },
01282 { "(bad)", XX, XX, XX },
01283 { "sarA", Eb, I1, XX },
01284 },
01285
01286 {
01287 { "rolQ", Ev, I1, XX },
01288 { "rorQ", Ev, I1, XX },
01289 { "rclQ", Ev, I1, XX },
01290 { "rcrQ", Ev, I1, XX },
01291 { "shlQ", Ev, I1, XX },
01292 { "shrQ", Ev, I1, XX },
01293 { "(bad)", XX, XX, XX},
01294 { "sarQ", Ev, I1, XX },
01295 },
01296
01297 {
01298 { "rolA", Eb, CL, XX },
01299 { "rorA", Eb, CL, XX },
01300 { "rclA", Eb, CL, XX },
01301 { "rcrA", Eb, CL, XX },
01302 { "shlA", Eb, CL, XX },
01303 { "shrA", Eb, CL, XX },
01304 { "(bad)", XX, XX, XX },
01305 { "sarA", Eb, CL, XX },
01306 },
01307
01308 {
01309 { "rolQ", Ev, CL, XX },
01310 { "rorQ", Ev, CL, XX },
01311 { "rclQ", Ev, CL, XX },
01312 { "rcrQ", Ev, CL, XX },
01313 { "shlQ", Ev, CL, XX },
01314 { "shrQ", Ev, CL, XX },
01315 { "(bad)", XX, XX, XX },
01316 { "sarQ", Ev, CL, XX }
01317 },
01318
01319 {
01320 { "testA", Eb, Ib, XX },
01321 { "(bad)", Eb, XX, XX },
01322 { "notA", Eb, XX, XX },
01323 { "negA", Eb, XX, XX },
01324 { "mulA", Eb, XX, XX },
01325 { "imulA", Eb, XX, XX },
01326 { "divA", Eb, XX, XX },
01327 { "idivA", Eb, XX, XX }
01328 },
01329
01330 {
01331 { "testQ", Ev, Iv, XX },
01332 { "(bad)", XX, XX, XX },
01333 { "notQ", Ev, XX, XX },
01334 { "negQ", Ev, XX, XX },
01335 { "mulQ", Ev, XX, XX },
01336 { "imulQ", Ev, XX, XX },
01337 { "divQ", Ev, XX, XX },
01338 { "idivQ", Ev, XX, XX },
01339 },
01340
01341 {
01342 { "incA", Eb, XX, XX },
01343 { "decA", Eb, XX, XX },
01344 { "(bad)", XX, XX, XX },
01345 { "(bad)", XX, XX, XX },
01346 { "(bad)", XX, XX, XX },
01347 { "(bad)", XX, XX, XX },
01348 { "(bad)", XX, XX, XX },
01349 { "(bad)", XX, XX, XX },
01350 },
01351
01352 {
01353 { "incQ", Ev, XX, XX },
01354 { "decQ", Ev, XX, XX },
01355 { "callT", indirEv, XX, XX },
01356 { "JcallT", indirEp, XX, XX },
01357 { "jmpT", indirEv, XX, XX },
01358 { "JjmpT", indirEp, XX, XX },
01359 { "pushU", Ev, XX, XX },
01360 { "(bad)", XX, XX, XX },
01361 },
01362
01363 {
01364 { "sldtQ", Ev, XX, XX },
01365 { "strQ", Ev, XX, XX },
01366 { "lldt", Ew, XX, XX },
01367 { "ltr", Ew, XX, XX },
01368 { "verr", Ew, XX, XX },
01369 { "verw", Ew, XX, XX },
01370 { "(bad)", XX, XX, XX },
01371 { "(bad)", XX, XX, XX }
01372 },
01373
01374 {
01375 { "sgdtIQ", M, XX, XX },
01376 { "sidtIQ", PNI_Fixup, 0, XX, XX },
01377 { "lgdt{Q|Q||}", M, XX, XX },
01378 { "lidt{Q|Q||}", M, XX, XX },
01379 { "smswQ", Ev, XX, XX },
01380 { "(bad)", XX, XX, XX },
01381 { "lmsw", Ew, XX, XX },
01382 { "invlpg", INVLPG_Fixup, w_mode, XX, XX },
01383 },
01384
01385 {
01386 { "(bad)", XX, XX, XX },
01387 { "(bad)", XX, XX, XX },
01388 { "(bad)", XX, XX, XX },
01389 { "(bad)", XX, XX, XX },
01390 { "btQ", Ev, Ib, XX },
01391 { "btsQ", Ev, Ib, XX },
01392 { "btrQ", Ev, Ib, XX },
01393 { "btcQ", Ev, Ib, XX },
01394 },
01395
01396 {
01397 { "(bad)", XX, XX, XX },
01398 { "cmpxchg8b", Eq, XX, XX },
01399 { "(bad)", XX, XX, XX },
01400 { "(bad)", XX, XX, XX },
01401 { "(bad)", XX, XX, XX },
01402 { "(bad)", XX, XX, XX },
01403 { "(bad)", XX, XX, XX },
01404 { "(bad)", XX, XX, XX },
01405 },
01406
01407 {
01408 { "(bad)", XX, XX, XX },
01409 { "(bad)", XX, XX, XX },
01410 { "psrlw", MS, Ib, XX },
01411 { "(bad)", XX, XX, XX },
01412 { "psraw", MS, Ib, XX },
01413 { "(bad)", XX, XX, XX },
01414 { "psllw", MS, Ib, XX },
01415 { "(bad)", XX, XX, XX },
01416 },
01417
01418 {
01419 { "(bad)", XX, XX, XX },
01420 { "(bad)", XX, XX, XX },
01421 { "psrld", MS, Ib, XX },
01422 { "(bad)", XX, XX, XX },
01423 { "psrad", MS, Ib, XX },
01424 { "(bad)", XX, XX, XX },
01425 { "pslld", MS, Ib, XX },
01426 { "(bad)", XX, XX, XX },
01427 },
01428
01429 {
01430 { "(bad)", XX, XX, XX },
01431 { "(bad)", XX, XX, XX },
01432 { "psrlq", MS, Ib, XX },
01433 { "psrldq", MS, Ib, XX },
01434 { "(bad)", XX, XX, XX },
01435 { "(bad)", XX, XX, XX },
01436 { "psllq", MS, Ib, XX },
01437 { "pslldq", MS, Ib, XX },
01438 },
01439
01440 {
01441 { "fxsave", Ev, XX, XX },
01442 { "fxrstor", Ev, XX, XX },
01443 { "ldmxcsr", Ev, XX, XX },
01444 { "stmxcsr", Ev, XX, XX },
01445 { "(bad)", XX, XX, XX },
01446 { "lfence", OP_0fae, 0, XX, XX },
01447 { "mfence", OP_0fae, 0, XX, XX },
01448 { "clflush", OP_0fae, 0, XX, XX },
01449 },
01450
01451 {
01452 { "prefetchnta", Ev, XX, XX },
01453 { "prefetcht0", Ev, XX, XX },
01454 { "prefetcht1", Ev, XX, XX },
01455 { "prefetcht2", Ev, XX, XX },
01456 { "(bad)", XX, XX, XX },
01457 { "(bad)", XX, XX, XX },
01458 { "(bad)", XX, XX, XX },
01459 { "(bad)", XX, XX, XX },
01460 },
01461
01462 {
01463 { "prefetch", Eb, XX, XX },
01464 { "prefetchw", Eb, XX, XX },
01465 { "(bad)", XX, XX, XX },
01466 { "(bad)", XX, XX, XX },
01467 { "(bad)", XX, XX, XX },
01468 { "(bad)", XX, XX, XX },
01469 { "(bad)", XX, XX, XX },
01470 { "(bad)", XX, XX, XX },
01471 },
01472
01473 {
01474 { "xstorerng", OP_0f07, 0, XX, XX },
01475 { "xcryptecb", OP_0f07, 0, XX, XX },
01476 { "xcryptcbc", OP_0f07, 0, XX, XX },
01477 { "(bad)", OP_0f07, 0, XX, XX },
01478 { "xcryptcfb", OP_0f07, 0, XX, XX },
01479 { "xcryptofb", OP_0f07, 0, XX, XX },
01480 { "(bad)", OP_0f07, 0, XX, XX },
01481 { "(bad)", OP_0f07, 0, XX, XX },
01482 },
01483
01484 {
01485 { "montmul", OP_0f07, 0, XX, XX },
01486 { "xsha1", OP_0f07, 0, XX, XX },
01487 { "xsha256", OP_0f07, 0, XX, XX },
01488 { "(bad)", OP_0f07, 0, XX, XX },
01489 { "(bad)", OP_0f07, 0, XX, XX },
01490 { "(bad)", OP_0f07, 0, XX, XX },
01491 { "(bad)", OP_0f07, 0, XX, XX },
01492 { "(bad)", OP_0f07, 0, XX, XX },
01493 }
01494 };
01495
01496 static const struct dis386 prefix_user_table[][4] = {
01497
01498 {
01499 { "addps", XM, EX, XX },
01500 { "addss", XM, EX, XX },
01501 { "addpd", XM, EX, XX },
01502 { "addsd", XM, EX, XX },
01503 },
01504
01505 {
01506 { "", XM, EX, OPSIMD },
01507 { "", XM, EX, OPSIMD },
01508 { "", XM, EX, OPSIMD },
01509 { "", XM, EX, OPSIMD },
01510 },
01511
01512 {
01513 { "cvtpi2ps", XM, EM, XX },
01514 { "cvtsi2ssY", XM, Ev, XX },
01515 { "cvtpi2pd", XM, EM, XX },
01516 { "cvtsi2sdY", XM, Ev, XX },
01517 },
01518
01519 {
01520 { "cvtps2pi", MX, EX, XX },
01521 { "cvtss2siY", Gv, EX, XX },
01522 { "cvtpd2pi", MX, EX, XX },
01523 { "cvtsd2siY", Gv, EX, XX },
01524 },
01525
01526 {
01527 { "cvttps2pi", MX, EX, XX },
01528 { "cvttss2siY", Gv, EX, XX },
01529 { "cvttpd2pi", MX, EX, XX },
01530 { "cvttsd2siY", Gv, EX, XX },
01531 },
01532
01533 {
01534 { "divps", XM, EX, XX },
01535 { "divss", XM, EX, XX },
01536 { "divpd", XM, EX, XX },
01537 { "divsd", XM, EX, XX },
01538 },
01539
01540 {
01541 { "maxps", XM, EX, XX },
01542 { "maxss", XM, EX, XX },
01543 { "maxpd", XM, EX, XX },
01544 { "maxsd", XM, EX, XX },
01545 },
01546
01547 {
01548 { "minps", XM, EX, XX },
01549 { "minss", XM, EX, XX },
01550 { "minpd", XM, EX, XX },
01551 { "minsd", XM, EX, XX },
01552 },
01553
01554 {
01555 { "movups", XM, EX, XX },
01556 { "movss", XM, EX, XX },
01557 { "movupd", XM, EX, XX },
01558 { "movsd", XM, EX, XX },
01559 },
01560
01561 {
01562 { "movups", EX, XM, XX },
01563 { "movss", EX, XM, XX },
01564 { "movupd", EX, XM, XX },
01565 { "movsd", EX, XM, XX },
01566 },
01567
01568 {
01569 { "mulps", XM, EX, XX },
01570 { "mulss", XM, EX, XX },
01571 { "mulpd", XM, EX, XX },
01572 { "mulsd", XM, EX, XX },
01573 },
01574
01575 {
01576 { "rcpps", XM, EX, XX },
01577 { "rcpss", XM, EX, XX },
01578 { "(bad)", XM, EX, XX },
01579 { "(bad)", XM, EX, XX },
01580 },
01581
01582 {
01583 { "rsqrtps", XM, EX, XX },
01584 { "rsqrtss", XM, EX, XX },
01585 { "(bad)", XM, EX, XX },
01586 { "(bad)", XM, EX, XX },
01587 },
01588
01589 {
01590 { "sqrtps", XM, EX, XX },
01591 { "sqrtss", XM, EX, XX },
01592 { "sqrtpd", XM, EX, XX },
01593 { "sqrtsd", XM, EX, XX },
01594 },
01595
01596 {
01597 { "subps", XM, EX, XX },
01598 { "subss", XM, EX, XX },
01599 { "subpd", XM, EX, XX },
01600 { "subsd", XM, EX, XX },
01601 },
01602
01603 {
01604 { "(bad)", XM, EX, XX },
01605 { "cvtdq2pd", XM, EX, XX },
01606 { "cvttpd2dq", XM, EX, XX },
01607 { "cvtpd2dq", XM, EX, XX },
01608 },
01609
01610 {
01611 { "cvtdq2ps", XM, EX, XX },
01612 { "cvttps2dq",XM, EX, XX },
01613 { "cvtps2dq",XM, EX, XX },
01614 { "(bad)", XM, EX, XX },
01615 },
01616
01617 {
01618 { "cvtps2pd", XM, EX, XX },
01619 { "cvtss2sd", XM, EX, XX },
01620 { "cvtpd2ps", XM, EX, XX },
01621 { "cvtsd2ss", XM, EX, XX },
01622 },
01623
01624 {
01625 { "maskmovq", MX, MS, XX },
01626 { "(bad)", XM, EX, XX },
01627 { "maskmovdqu", XM, EX, XX },
01628 { "(bad)", XM, EX, XX },
01629 },
01630
01631 {
01632 { "movq", MX, EM, XX },
01633 { "movdqu", XM, EX, XX },
01634 { "movdqa", XM, EX, XX },
01635 { "(bad)", XM, EX, XX },
01636 },
01637
01638 {
01639 { "movq", EM, MX, XX },
01640 { "movdqu", EX, XM, XX },
01641 { "movdqa", EX, XM, XX },
01642 { "(bad)", EX, XM, XX },
01643 },
01644
01645 {
01646 { "(bad)", EX, XM, XX },
01647 { "movq2dq", XM, MS, XX },
01648 { "movq", EX, XM, XX },
01649 { "movdq2q", MX, XS, XX },
01650 },
01651
01652 {
01653 { "pshufw", MX, EM, Ib },
01654 { "pshufhw", XM, EX, Ib },
01655 { "pshufd", XM, EX, Ib },
01656 { "pshuflw", XM, EX, Ib },
01657 },
01658
01659 {
01660 { "movd", Edq, MX, XX },
01661 { "movq", XM, EX, XX },
01662 { "movd", Edq, XM, XX },
01663 { "(bad)", Ed, XM, XX },
01664 },
01665
01666 {
01667 { "(bad)", MX, EX, XX },
01668 { "(bad)", XM, EX, XX },
01669 { "punpckhqdq", XM, EX, XX },
01670 { "(bad)", XM, EX, XX },
01671 },
01672
01673 {
01674 { "movntq", EM, MX, XX },
01675 { "(bad)", EM, XM, XX },
01676 { "movntdq", EM, XM, XX },
01677 { "(bad)", EM, XM, XX },
01678 },
01679
01680 {
01681 { "(bad)", MX, EX, XX },
01682 { "(bad)", XM, EX, XX },
01683 { "punpcklqdq", XM, EX, XX },
01684 { "(bad)", XM, EX, XX },
01685 },
01686
01687 {
01688 { "(bad)", MX, EX, XX },
01689 { "(bad)", XM, EX, XX },
01690 { "addsubpd", XM, EX, XX },
01691 { "addsubps", XM, EX, XX },
01692 },
01693
01694 {
01695 { "(bad)", MX, EX, XX },
01696 { "(bad)", XM, EX, XX },
01697 { "haddpd", XM, EX, XX },
01698 { "haddps", XM, EX, XX },
01699 },
01700
01701 {
01702 { "(bad)", MX, EX, XX },
01703 { "(bad)", XM, EX, XX },
01704 { "hsubpd", XM, EX, XX },
01705 { "hsubps", XM, EX, XX },
01706 },
01707
01708 {
01709 { "movlpX", XM, EX, SIMD_Fixup, 'h' },
01710 { "movsldup", XM, EX, XX },
01711 { "movlpd", XM, EX, XX },
01712 { "movddup", XM, EX, XX },
01713 },
01714
01715 {
01716 { "movhpX", XM, EX, SIMD_Fixup, 'l' },
01717 { "movshdup", XM, EX, XX },
01718 { "movhpd", XM, EX, XX },
01719 { "(bad)", XM, EX, XX },
01720 },
01721
01722 {
01723 { "(bad)", XM, EX, XX },
01724 { "(bad)", XM, EX, XX },
01725 { "(bad)", XM, EX, XX },
01726 { "lddqu", XM, M, XX },
01727 },
01728 };
01729
01730 static const struct dis386 x86_64_table[][2] = {
01731 {
01732 { "arpl", Ew, Gw, XX },
01733 { "movs{||lq|xd}", Gv, Ed, XX },
01734 },
01735 };
01736
01737 #define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
01738
01739 static void
01740 ckprefix (void)
01741 {
01742 int newrex;
01743 rex = 0;
01744 prefixes = 0;
01745 used_prefixes = 0;
01746 rex_used = 0;
01747 while (1)
01748 {
01749 FETCH_DATA (the_info, codep + 1);
01750 newrex = 0;
01751 switch (*codep)
01752 {
01753
01754 case 0x40:
01755 case 0x41:
01756 case 0x42:
01757 case 0x43:
01758 case 0x44:
01759 case 0x45:
01760 case 0x46:
01761 case 0x47:
01762 case 0x48:
01763 case 0x49:
01764 case 0x4a:
01765 case 0x4b:
01766 case 0x4c:
01767 case 0x4d:
01768 case 0x4e:
01769 case 0x4f:
01770 if (mode_64bit)
01771 newrex = *codep;
01772 else
01773 return;
01774 break;
01775 case 0xf3:
01776 prefixes |= PREFIX_REPZ;
01777 break;
01778 case 0xf2:
01779 prefixes |= PREFIX_REPNZ;
01780 break;
01781 case 0xf0:
01782 prefixes |= PREFIX_LOCK;
01783 break;
01784 case 0x2e:
01785 prefixes |= PREFIX_CS;
01786 break;
01787 case 0x36:
01788 prefixes |= PREFIX_SS;
01789 break;
01790 case 0x3e:
01791 prefixes |= PREFIX_DS;
01792 break;
01793 case 0x26:
01794 prefixes |= PREFIX_ES;
01795 break;
01796 case 0x64:
01797 prefixes |= PREFIX_FS;
01798 break;
01799 case 0x65:
01800 prefixes |= PREFIX_GS;
01801 break;
01802 case 0x66:
01803 prefixes |= PREFIX_DATA;
01804 break;
01805 case 0x67:
01806 prefixes |= PREFIX_ADDR;
01807 break;
01808 case FWAIT_OPCODE:
01809
01810
01811
01812 if (prefixes)
01813 {
01814 prefixes |= PREFIX_FWAIT;
01815 codep++;
01816 return;
01817 }
01818 prefixes = PREFIX_FWAIT;
01819 break;
01820 default:
01821 return;
01822 }
01823
01824 if (rex)
01825 {
01826 oappend (prefix_name (rex, 0));
01827 oappend (" ");
01828 }
01829 rex = newrex;
01830 codep++;
01831 }
01832 }
01833
01834
01835
01836
01837 static const char *
01838 prefix_name (int pref, int sizeflag)
01839 {
01840 switch (pref)
01841 {
01842
01843 case 0x40:
01844 return "rex";
01845 case 0x41:
01846 return "rexZ";
01847 case 0x42:
01848 return "rexY";
01849 case 0x43:
01850 return "rexYZ";
01851 case 0x44:
01852 return "rexX";
01853 case 0x45:
01854 return "rexXZ";
01855 case 0x46:
01856 return "rexXY";
01857 case 0x47:
01858 return "rexXYZ";
01859 case 0x48:
01860 return "rex64";
01861 case 0x49:
01862 return "rex64Z";
01863 case 0x4a:
01864 return "rex64Y";
01865 case 0x4b:
01866 return "rex64YZ";
01867 case 0x4c:
01868 return "rex64X";
01869 case 0x4d:
01870 return "rex64XZ";
01871 case 0x4e:
01872 return "rex64XY";
01873 case 0x4f:
01874 return "rex64XYZ";
01875 case 0xf3:
01876 return "repz";
01877 case 0xf2:
01878 return "repnz";
01879 case 0xf0:
01880 return "lock";
01881 case 0x2e:
01882 return "cs";
01883 case 0x36:
01884 return "ss";
01885 case 0x3e:
01886 return "ds";
01887 case 0x26:
01888 return "es";
01889 case 0x64:
01890 return "fs";
01891 case 0x65:
01892 return "gs";
01893 case 0x66:
01894 return (sizeflag & DFLAG) ? "data16" : "data32";
01895 case 0x67:
01896 if (mode_64bit)
01897 return (sizeflag & AFLAG) ? "addr32" : "addr64";
01898 else
01899 return ((sizeflag & AFLAG) && !mode_64bit) ? "addr16" : "addr32";
01900 case FWAIT_OPCODE:
01901 return "fwait";
01902 default:
01903 return NULL;
01904 }
01905 }
01906
01907 static char op1out[100], op2out[100], op3out[100];
01908 static int op_ad, op_index[3];
01909 static int two_source_ops;
01910 static bfd_vma op_address[3];
01911 static bfd_vma op_riprel[3];
01912 static bfd_vma start_pc;
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923 static char intel_syntax;
01924 static char open_char;
01925 static char close_char;
01926 static char separator_char;
01927 static char scale_char;
01928
01929
01930
01931
01932 int
01933 print_insn_i386_att (bfd_vma pc, disassemble_info *info)
01934 {
01935 intel_syntax = 0;
01936
01937 return print_insn (pc, info);
01938 }
01939
01940 int
01941 print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
01942 {
01943 intel_syntax = 1;
01944
01945 return print_insn (pc, info);
01946 }
01947
01948 int
01949 print_insn_i386 (bfd_vma pc, disassemble_info *info)
01950 {
01951 intel_syntax = -1;
01952
01953 return print_insn (pc, info);
01954 }
01955
01956 static int
01957 print_insn (bfd_vma pc, disassemble_info *info)
01958 {
01959 const struct dis386 *dp;
01960 int i;
01961 char *first, *second, *third;
01962 int needcomma;
01963 unsigned char uses_SSE_prefix, uses_LOCK_prefix;
01964 int sizeflag;
01965 const char *p;
01966 struct dis_private priv;
01967
01968 mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
01969 || info->mach == bfd_mach_x86_64);
01970
01971 if (intel_syntax == (char) -1)
01972 intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
01973 || info->mach == bfd_mach_x86_64_intel_syntax);
01974
01975 if (info->mach == bfd_mach_i386_i386
01976 || info->mach == bfd_mach_x86_64
01977 || info->mach == bfd_mach_i386_i386_intel_syntax
01978 || info->mach == bfd_mach_x86_64_intel_syntax)
01979 priv.orig_sizeflag = AFLAG | DFLAG;
01980 else if (info->mach == bfd_mach_i386_i8086)
01981 priv.orig_sizeflag = 0;
01982 else
01983 abort ();
01984
01985 for (p = info->disassembler_options; p != NULL; )
01986 {
01987 if (strncmp (p, "x86-64", 6) == 0)
01988 {
01989 mode_64bit = 1;
01990 priv.orig_sizeflag = AFLAG | DFLAG;
01991 }
01992 else if (strncmp (p, "i386", 4) == 0)
01993 {
01994 mode_64bit = 0;
01995 priv.orig_sizeflag = AFLAG | DFLAG;
01996 }
01997 else if (strncmp (p, "i8086", 5) == 0)
01998 {
01999 mode_64bit = 0;
02000 priv.orig_sizeflag = 0;
02001 }
02002 else if (strncmp (p, "intel", 5) == 0)
02003 {
02004 intel_syntax = 1;
02005 }
02006 else if (strncmp (p, "att", 3) == 0)
02007 {
02008 intel_syntax = 0;
02009 }
02010 else if (strncmp (p, "addr", 4) == 0)
02011 {
02012 if (p[4] == '1' && p[5] == '6')
02013 priv.orig_sizeflag &= ~AFLAG;
02014 else if (p[4] == '3' && p[5] == '2')
02015 priv.orig_sizeflag |= AFLAG;
02016 }
02017 else if (strncmp (p, "data", 4) == 0)
02018 {
02019 if (p[4] == '1' && p[5] == '6')
02020 priv.orig_sizeflag &= ~DFLAG;
02021 else if (p[4] == '3' && p[5] == '2')
02022 priv.orig_sizeflag |= DFLAG;
02023 }
02024 else if (strncmp (p, "suffix", 6) == 0)
02025 priv.orig_sizeflag |= SUFFIX_ALWAYS;
02026
02027 p = strchr (p, ',');
02028 if (p != NULL)
02029 p++;
02030 }
02031
02032 if (intel_syntax)
02033 {
02034 names64 = intel_names64;
02035 names32 = intel_names32;
02036 names16 = intel_names16;
02037 names8 = intel_names8;
02038 names8rex = intel_names8rex;
02039 names_seg = intel_names_seg;
02040 index16 = intel_index16;
02041 open_char = '[';
02042 close_char = ']';
02043 separator_char = '+';
02044 scale_char = '*';
02045 }
02046 else
02047 {
02048 names64 = att_names64;
02049 names32 = att_names32;
02050 names16 = att_names16;
02051 names8 = att_names8;
02052 names8rex = att_names8rex;
02053 names_seg = att_names_seg;
02054 index16 = att_index16;
02055 open_char = '(';
02056 close_char = ')';
02057 separator_char = ',';
02058 scale_char = ',';
02059 }
02060
02061
02062
02063 info->bytes_per_line = 7;
02064
02065 info->private_data = &priv;
02066 priv.max_fetched = priv.the_buffer;
02067 priv.insn_start = pc;
02068
02069 obuf[0] = 0;
02070 op1out[0] = 0;
02071 op2out[0] = 0;
02072 op3out[0] = 0;
02073
02074 op_index[0] = op_index[1] = op_index[2] = -1;
02075
02076 the_info = info;
02077 start_pc = pc;
02078 start_codep = priv.the_buffer;
02079 codep = priv.the_buffer;
02080
02081 if (setjmp (priv.bailout) != 0)
02082 {
02083 const char *name;
02084
02085
02086
02087
02088 if (codep > priv.the_buffer)
02089 {
02090 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
02091 if (name != NULL)
02092 (*info->fprintf_func) (info->stream, "%s", name);
02093 else
02094 {
02095
02096 (*info->fprintf_func) (info->stream, ".byte 0x%x",
02097 (unsigned int) priv.the_buffer[0]);
02098 }
02099
02100 return 1;
02101 }
02102
02103 return -1;
02104 }
02105
02106 obufp = obuf;
02107 ckprefix ();
02108
02109 insn_codep = codep;
02110 sizeflag = priv.orig_sizeflag;
02111
02112 FETCH_DATA (info, codep + 1);
02113 two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
02114
02115 if ((prefixes & PREFIX_FWAIT)
02116 && ((*codep < 0xd8) || (*codep > 0xdf)))
02117 {
02118 const char *name;
02119
02120
02121
02122 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
02123 if (name == NULL)
02124 name = INTERNAL_DISASSEMBLER_ERROR;
02125 (*info->fprintf_func) (info->stream, "%s", name);
02126 return 1;
02127 }
02128
02129 if (*codep == 0x0f)
02130 {
02131 FETCH_DATA (info, codep + 2);
02132 dp = &dis386_twobyte[*++codep];
02133 need_modrm = twobyte_has_modrm[*codep];
02134 uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep];
02135 uses_LOCK_prefix = (*codep & ~0x02) == 0x20;
02136 }
02137 else
02138 {
02139 dp = &dis386[*codep];
02140 need_modrm = onebyte_has_modrm[*codep];
02141 uses_SSE_prefix = 0;
02142 uses_LOCK_prefix = 0;
02143 }
02144 codep++;
02145
02146 if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ))
02147 {
02148 oappend ("repz ");
02149 used_prefixes |= PREFIX_REPZ;
02150 }
02151 if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ))
02152 {
02153 oappend ("repnz ");
02154 used_prefixes |= PREFIX_REPNZ;
02155 }
02156 if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK))
02157 {
02158 oappend ("lock ");
02159 used_prefixes |= PREFIX_LOCK;
02160 }
02161
02162 if (prefixes & PREFIX_ADDR)
02163 {
02164 sizeflag ^= AFLAG;
02165 if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
02166 {
02167 if ((sizeflag & AFLAG) || mode_64bit)
02168 oappend ("addr32 ");
02169 else
02170 oappend ("addr16 ");
02171 used_prefixes |= PREFIX_ADDR;
02172 }
02173 }
02174
02175 if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
02176 {
02177 sizeflag ^= DFLAG;
02178 if (dp->bytemode3 == cond_jump_mode
02179 && dp->bytemode1 == v_mode
02180 && !intel_syntax)
02181 {
02182 if (sizeflag & DFLAG)
02183 oappend ("data32 ");
02184 else
02185 oappend ("data16 ");
02186 used_prefixes |= PREFIX_DATA;
02187 }
02188 }
02189
02190 if (need_modrm)
02191 {
02192 FETCH_DATA (info, codep + 1);
02193 mod = (*codep >> 6) & 3;
02194 reg = (*codep >> 3) & 7;
02195 rm = *codep & 7;
02196 }
02197
02198 if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
02199 {
02200 dofloat (sizeflag);
02201 }
02202 else
02203 {
02204 int index;
02205 if (dp->name == NULL)
02206 {
02207 switch (dp->bytemode1)
02208 {
02209 case USE_GROUPS:
02210 dp = &grps[dp->bytemode2][reg];
02211 break;
02212
02213 case USE_PREFIX_USER_TABLE:
02214 index = 0;
02215 used_prefixes |= (prefixes & PREFIX_REPZ);
02216 if (prefixes & PREFIX_REPZ)
02217 index = 1;
02218 else
02219 {
02220 used_prefixes |= (prefixes & PREFIX_DATA);
02221 if (prefixes & PREFIX_DATA)
02222 index = 2;
02223 else
02224 {
02225 used_prefixes |= (prefixes & PREFIX_REPNZ);
02226 if (prefixes & PREFIX_REPNZ)
02227 index = 3;
02228 }
02229 }
02230 dp = &prefix_user_table[dp->bytemode2][index];
02231 break;
02232
02233 case X86_64_SPECIAL:
02234 dp = &x86_64_table[dp->bytemode2][mode_64bit];
02235 break;
02236
02237 default:
02238 oappend (INTERNAL_DISASSEMBLER_ERROR);
02239 break;
02240 }
02241 }
02242
02243 if (putop (dp->name, sizeflag) == 0)
02244 {
02245 obufp = op1out;
02246 op_ad = 2;
02247 if (dp->op1)
02248 (*dp->op1) (dp->bytemode1, sizeflag);
02249
02250 obufp = op2out;
02251 op_ad = 1;
02252 if (dp->op2)
02253 (*dp->op2) (dp->bytemode2, sizeflag);
02254
02255 obufp = op3out;
02256 op_ad = 0;
02257 if (dp->op3)
02258 (*dp->op3) (dp->bytemode3, sizeflag);
02259 }
02260 }
02261
02262
02263
02264
02265
02266 if ((prefixes & ~used_prefixes) != 0)
02267 {
02268 const char *name;
02269
02270 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
02271 if (name == NULL)
02272 name = INTERNAL_DISASSEMBLER_ERROR;
02273 (*info->fprintf_func) (info->stream, "%s", name);
02274 return 1;
02275 }
02276 if (rex & ~rex_used)
02277 {
02278 const char *name;
02279 name = prefix_name (rex | 0x40, priv.orig_sizeflag);
02280 if (name == NULL)
02281 name = INTERNAL_DISASSEMBLER_ERROR;
02282 (*info->fprintf_func) (info->stream, "%s ", name);
02283 }
02284
02285 obufp = obuf + strlen (obuf);
02286 for (i = strlen (obuf); i < 6; i++)
02287 oappend (" ");
02288 oappend (" ");
02289 (*info->fprintf_func) (info->stream, "%s", obuf);
02290
02291
02292
02293 if (intel_syntax || two_source_ops)
02294 {
02295 first = op1out;
02296 second = op2out;
02297 third = op3out;
02298 op_ad = op_index[0];
02299 op_index[0] = op_index[2];
02300 op_index[2] = op_ad;
02301 }
02302 else
02303 {
02304 first = op3out;
02305 second = op2out;
02306 third = op1out;
02307 }
02308 needcomma = 0;
02309 if (*first)
02310 {
02311 if (op_index[0] != -1 && !op_riprel[0])
02312 (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
02313 else
02314 (*info->fprintf_func) (info->stream, "%s", first);
02315 needcomma = 1;
02316 }
02317 if (*second)
02318 {
02319 if (needcomma)
02320 (*info->fprintf_func) (info->stream, ",");
02321 if (op_index[1] != -1 && !op_riprel[1])
02322 (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
02323 else
02324 (*info->fprintf_func) (info->stream, "%s", second);
02325 needcomma = 1;
02326 }
02327 if (*third)
02328 {
02329 if (needcomma)
02330 (*info->fprintf_func) (info->stream, ",");
02331 if (op_index[2] != -1 && !op_riprel[2])
02332 (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
02333 else
02334 (*info->fprintf_func) (info->stream, "%s", third);
02335 }
02336 for (i = 0; i < 3; i++)
02337 if (op_index[i] != -1 && op_riprel[i])
02338 {
02339 (*info->fprintf_func) (info->stream, " # ");
02340 (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
02341 + op_address[op_index[i]]), info);
02342 }
02343 return codep - priv.the_buffer;
02344 }
02345
02346 static const char *float_mem[] = {
02347
02348 "fadd{s||s|}",
02349 "fmul{s||s|}",
02350 "fcom{s||s|}",
02351 "fcomp{s||s|}",
02352 "fsub{s||s|}",
02353 "fsubr{s||s|}",
02354 "fdiv{s||s|}",
02355 "fdivr{s||s|}",
02356
02357 "fld{s||s|}",
02358 "(bad)",
02359 "fst{s||s|}",
02360 "fstp{s||s|}",
02361 "fldenvIC",
02362 "fldcw",
02363 "fNstenvIC",
02364 "fNstcw",
02365
02366 "fiadd{l||l|}",
02367 "fimul{l||l|}",
02368 "ficom{l||l|}",
02369 "ficomp{l||l|}",
02370 "fisub{l||l|}",
02371 "fisubr{l||l|}",
02372 "fidiv{l||l|}",
02373 "fidivr{l||l|}",
02374
02375 "fild{l||l|}",
02376 "fisttp{l||l|}",
02377 "fist{l||l|}",
02378 "fistp{l||l|}",
02379 "(bad)",
02380 "fld{t||t|}",
02381 "(bad)",
02382 "fstp{t||t|}",
02383
02384 "fadd{l||l|}",
02385 "fmul{l||l|}",
02386 "fcom{l||l|}",
02387 "fcomp{l||l|}",
02388 "fsub{l||l|}",
02389 "fsubr{l||l|}",
02390 "fdiv{l||l|}",
02391 "fdivr{l||l|}",
02392
02393 "fld{l||l|}",
02394 "fisttp{ll||ll|}",
02395 "fst{l||l|}",
02396 "fstp{l||l|}",
02397 "frstorIC",
02398 "(bad)",
02399 "fNsaveIC",
02400 "fNstsw",
02401
02402 "fiadd",
02403 "fimul",
02404 "ficom",
02405 "ficomp",
02406 "fisub",
02407 "fisubr",
02408 "fidiv",
02409 "fidivr",
02410
02411 "fild",
02412 "fisttp",
02413 "fist",
02414 "fistp",
02415 "fbld",
02416 "fild{ll||ll|}",
02417 "fbstp",
02418 "fistp{ll||ll|}",
02419 };
02420
02421 static const unsigned char float_mem_mode[] = {
02422
02423 d_mode,
02424 d_mode,
02425 d_mode,
02426 d_mode,
02427 d_mode,
02428 d_mode,
02429 d_mode,
02430 d_mode,
02431
02432 d_mode,
02433 0,
02434 d_mode,
02435 d_mode,
02436 0,
02437 w_mode,
02438 0,
02439 w_mode,
02440
02441 d_mode,
02442 d_mode,
02443 d_mode,
02444 d_mode,
02445 d_mode,
02446 d_mode,
02447 d_mode,
02448 d_mode,
02449
02450 d_mode,
02451 d_mode,
02452 d_mode,
02453 d_mode,
02454 0,
02455 t_mode,
02456 0,
02457 t_mode,
02458
02459 q_mode,
02460 q_mode,
02461 q_mode,
02462 q_mode,
02463 q_mode,
02464 q_mode,
02465 q_mode,
02466 q_mode,
02467
02468 q_mode,
02469 q_mode,
02470 q_mode,
02471 q_mode,
02472 0,
02473 0,
02474 0,
02475 w_mode,
02476
02477 w_mode,
02478 w_mode,
02479 w_mode,
02480 w_mode,
02481 w_mode,
02482 w_mode,
02483 w_mode,
02484 w_mode,
02485
02486 w_mode,
02487 w_mode,
02488 w_mode,
02489 w_mode,
02490 t_mode,
02491 q_mode,
02492 t_mode,
02493 q_mode
02494 };
02495
02496 #define ST OP_ST, 0
02497 #define STi OP_STi, 0
02498
02499 #define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0
02500 #define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0
02501 #define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0
02502 #define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0
02503 #define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0
02504 #define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0
02505 #define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0
02506 #define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0
02507 #define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0
02508
02509 static const struct dis386 float_reg[][8] = {
02510
02511 {
02512 { "fadd", ST, STi, XX },
02513 { "fmul", ST, STi, XX },
02514 { "fcom", STi, XX, XX },
02515 { "fcomp", STi, XX, XX },
02516 { "fsub", ST, STi, XX },
02517 { "fsubr", ST, STi, XX },
02518 { "fdiv", ST, STi, XX },
02519 { "fdivr", ST, STi, XX },
02520 },
02521
02522 {
02523 { "fld", STi, XX, XX },
02524 { "fxch", STi, XX, XX },
02525 { FGRPd9_2 },
02526 { "(bad)", XX, XX, XX },
02527 { FGRPd9_4 },
02528 { FGRPd9_5 },
02529 { FGRPd9_6 },
02530 { FGRPd9_7 },
02531 },
02532
02533 {
02534 { "fcmovb", ST, STi, XX },
02535 { "fcmove", ST, STi, XX },
02536 { "fcmovbe",ST, STi, XX },
02537 { "fcmovu", ST, STi, XX },
02538 { "(bad)", XX, XX, XX },
02539 { FGRPda_5 },
02540 { "(bad)", XX, XX, XX },
02541 { "(bad)", XX, XX, XX },
02542 },
02543
02544 {
02545 { "fcmovnb",ST, STi, XX },
02546 { "fcmovne",ST, STi, XX },
02547 { "fcmovnbe",ST, STi, XX },
02548 { "fcmovnu",ST, STi, XX },
02549 { FGRPdb_4 },
02550 { "fucomi", ST, STi, XX },
02551 { "fcomi", ST, STi, XX },
02552 { "(bad)", XX, XX, XX },
02553 },
02554
02555 {
02556 { "fadd", STi, ST, XX },
02557 { "fmul", STi, ST, XX },
02558 { "(bad)", XX, XX, XX },
02559 { "(bad)", XX, XX, XX },
02560 #if UNIXWARE_COMPAT
02561 { "fsub", STi, ST, XX },
02562 { "fsubr", STi, ST, XX },
02563 { "fdiv", STi, ST, XX },
02564 { "fdivr", STi, ST, XX },
02565 #else
02566 { "fsubr", STi, ST, XX },
02567 { "fsub", STi, ST, XX },
02568 { "fdivr", STi, ST, XX },
02569 { "fdiv", STi, ST, XX },
02570 #endif
02571 },
02572
02573 {
02574 { "ffree", STi, XX, XX },
02575 { "(bad)", XX, XX, XX },
02576 { "fst", STi, XX, XX },
02577 { "fstp", STi, XX, XX },
02578 { "fucom", STi, XX, XX },
02579 { "fucomp", STi, XX, XX },
02580 { "(bad)", XX, XX, XX },
02581 { "(bad)", XX, XX, XX },
02582 },
02583
02584 {
02585 { "faddp", STi, ST, XX },
02586 { "fmulp", STi, ST, XX },
02587 { "(bad)", XX, XX, XX },
02588 { FGRPde_3 },
02589 #if UNIXWARE_COMPAT
02590 { "fsubp", STi, ST, XX },
02591 { "fsubrp", STi, ST, XX },
02592 { "fdivp", STi, ST, XX },
02593 { "fdivrp", STi, ST, XX },
02594 #else
02595 { "fsubrp", STi, ST, XX },
02596 { "fsubp", STi, ST, XX },
02597 { "fdivrp", STi, ST, XX },
02598 { "fdivp", STi, ST, XX },
02599 #endif
02600 },
02601
02602 {
02603 { "ffreep", STi, XX, XX },
02604 { "(bad)", XX, XX, XX },
02605 { "(bad)", XX, XX, XX },
02606 { "(bad)", XX, XX, XX },
02607 { FGRPdf_4 },
02608 { "fucomip",ST, STi, XX },
02609 { "fcomip", ST, STi, XX },
02610 { "(bad)", XX, XX, XX },
02611 },
02612 };
02613
02614 static char *fgrps[][8] = {
02615
02616 {
02617 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
02618 },
02619
02620
02621 {
02622 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
02623 },
02624
02625
02626 {
02627 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
02628 },
02629
02630
02631 {
02632 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
02633 },
02634
02635
02636 {
02637 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
02638 },
02639
02640
02641 {
02642 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
02643 },
02644
02645
02646 {
02647 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
02648 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
02649 },
02650
02651
02652 {
02653 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
02654 },
02655
02656
02657 {
02658 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
02659 },
02660 };
02661
02662 static void
02663 dofloat (int sizeflag)
02664 {
02665 const struct dis386 *dp;
02666 unsigned char floatop;
02667
02668 floatop = codep[-1];
02669
02670 if (mod != 3)
02671 {
02672 int fp_indx = (floatop - 0xd8) * 8 + reg;
02673
02674 putop (float_mem[fp_indx], sizeflag);
02675 obufp = op1out;
02676 OP_E (float_mem_mode[fp_indx], sizeflag);
02677 return;
02678 }
02679
02680 MODRM_CHECK;
02681 codep++;
02682
02683 dp = &float_reg[floatop - 0xd8][reg];
02684 if (dp->name == NULL)
02685 {
02686 putop (fgrps[dp->bytemode1][rm], sizeflag);
02687
02688
02689 if (floatop == 0xdf && codep[-1] == 0xe0)
02690 strcpy (op1out, names16[0]);
02691 }
02692 else
02693 {
02694 putop (dp->name, sizeflag);
02695
02696 obufp = op1out;
02697 if (dp->op1)
02698 (*dp->op1) (dp->bytemode1, sizeflag);
02699 obufp = op2out;
02700 if (dp->op2)
02701 (*dp->op2) (dp->bytemode2, sizeflag);
02702 }
02703 }
02704
02705 static void
02706 OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
02707 {
02708 oappend ("%st");
02709 }
02710
02711 static void
02712 OP_STi (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
02713 {
02714 sprintf (scratchbuf, "%%st(%d)", rm);
02715 oappend (scratchbuf + intel_syntax);
02716 }
02717
02718
02719 static int
02720 putop (const char *template, int sizeflag)
02721 {
02722 const char *p;
02723 int alt = 0;
02724
02725 for (p = template; *p; p++)
02726 {
02727 switch (*p)
02728 {
02729 default:
02730 *obufp++ = *p;
02731 break;
02732 case '{':
02733 alt = 0;
02734 if (intel_syntax)
02735 alt += 1;
02736 if (mode_64bit)
02737 alt += 2;
02738 while (alt != 0)
02739 {
02740 while (*++p != '|')
02741 {
02742 if (*p == '}')
02743 {
02744
02745 strcpy (obuf, "(bad)");
02746 obufp = obuf + 5;
02747 return 1;
02748 }
02749 else if (*p == '\0')
02750 abort ();
02751 }
02752 alt--;
02753 }
02754
02755 case 'I':
02756 alt = 1;
02757 continue;
02758 case '|':
02759 while (*++p != '}')
02760 {
02761 if (*p == '\0')
02762 abort ();
02763 }
02764 break;
02765 case '}':
02766 break;
02767 case 'A':
02768 if (intel_syntax)
02769 break;
02770 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
02771 *obufp++ = 'b';
02772 break;
02773 case 'B':
02774 if (intel_syntax)
02775 break;
02776 if (sizeflag & SUFFIX_ALWAYS)
02777 *obufp++ = 'b';
02778 break;
02779 case 'C':
02780 if (intel_syntax && !alt)
02781 break;
02782 if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS))
02783 {
02784 if (sizeflag & DFLAG)
02785 *obufp++ = intel_syntax ? 'd' : 'l';
02786 else
02787 *obufp++ = intel_syntax ? 'w' : 's';
02788 used_prefixes |= (prefixes & PREFIX_DATA);
02789 }
02790 break;
02791 case 'E':
02792 if (mode_64bit)
02793 {
02794 if (sizeflag & AFLAG)
02795 *obufp++ = 'r';
02796 else
02797 *obufp++ = 'e';
02798 }
02799 else
02800 if (sizeflag & AFLAG)
02801 *obufp++ = 'e';
02802 used_prefixes |= (prefixes & PREFIX_ADDR);
02803 break;
02804 case 'F':
02805 if (intel_syntax)
02806 break;
02807 if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
02808 {
02809 if (sizeflag & AFLAG)
02810 *obufp++ = mode_64bit ? 'q' : 'l';
02811 else
02812 *obufp++ = mode_64bit ? 'l' : 'w';
02813 used_prefixes |= (prefixes & PREFIX_ADDR);
02814 }
02815 break;
02816 case 'H':
02817 if (intel_syntax)
02818 break;
02819 if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS
02820 || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS)
02821 {
02822 used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS);
02823 *obufp++ = ',';
02824 *obufp++ = 'p';
02825 if (prefixes & PREFIX_DS)
02826 *obufp++ = 't';
02827 else
02828 *obufp++ = 'n';
02829 }
02830 break;
02831 case 'J':
02832 if (intel_syntax)
02833 break;
02834 *obufp++ = 'l';
02835 break;
02836 case 'L':
02837 if (intel_syntax)
02838 break;
02839 if (sizeflag & SUFFIX_ALWAYS)
02840 *obufp++ = 'l';
02841 break;
02842 case 'N':
02843 if ((prefixes & PREFIX_FWAIT) == 0)
02844 *obufp++ = 'n';
02845 else
02846 used_prefixes |= PREFIX_FWAIT;
02847 break;
02848 case 'O':
02849 USED_REX (REX_MODE64);
02850 if (rex & REX_MODE64)
02851 *obufp++ = 'o';
02852 else
02853 *obufp++ = 'd';
02854 break;
02855 case 'T':
02856 if (intel_syntax)
02857 break;
02858 if (mode_64bit)
02859 {
02860 *obufp++ = 'q';
02861 break;
02862 }
02863
02864 case 'P':
02865 if (intel_syntax)
02866 break;
02867 if ((prefixes & PREFIX_DATA)
02868 || (rex & REX_MODE64)
02869 || (sizeflag & SUFFIX_ALWAYS))
02870 {
02871 USED_REX (REX_MODE64);
02872 if (rex & REX_MODE64)
02873 *obufp++ = 'q';
02874 else
02875 {
02876 if (sizeflag & DFLAG)
02877 *obufp++ = 'l';
02878 else
02879 *obufp++ = 'w';
02880 used_prefixes |= (prefixes & PREFIX_DATA);
02881 }
02882 }
02883 break;
02884 case 'U':
02885 if (intel_syntax)
02886 break;
02887 if (mode_64bit)
02888 {
02889 *obufp++ = 'q';
02890 break;
02891 }
02892
02893 case 'Q':
02894 if (intel_syntax && !alt)
02895 break;
02896 USED_REX (REX_MODE64);
02897 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
02898 {
02899 if (rex & REX_MODE64)
02900 *obufp++ = 'q';
02901 else
02902 {
02903 if (sizeflag & DFLAG)
02904 *obufp++ = intel_syntax ? 'd' : 'l';
02905 else
02906 *obufp++ = 'w';
02907 used_prefixes |= (prefixes & PREFIX_DATA);
02908 }
02909 }
02910 break;
02911 case 'R':
02912 USED_REX (REX_MODE64);
02913 if (intel_syntax)
02914 {
02915 if (rex & REX_MODE64)
02916 {
02917 *obufp++ = 'q';
02918 *obufp++ = 't';
02919 }
02920 else if (sizeflag & DFLAG)
02921 {
02922 *obufp++ = 'd';
02923 *obufp++ = 'q';
02924 }
02925 else
02926 {
02927 *obufp++ = 'w';
02928 *obufp++ = 'd';
02929 }
02930 }
02931 else
02932 {
02933 if (rex & REX_MODE64)
02934 *obufp++ = 'q';
02935 else if (sizeflag & DFLAG)
02936 *obufp++ = 'l';
02937 else
02938 *obufp++ = 'w';
02939 }
02940 if (!(rex & REX_MODE64))
02941 used_prefixes |= (prefixes & PREFIX_DATA);
02942 break;
02943 case 'S':
02944 if (intel_syntax)
02945 break;
02946 if (sizeflag & SUFFIX_ALWAYS)
02947 {
02948 if (rex & REX_MODE64)
02949 *obufp++ = 'q';
02950 else
02951 {
02952 if (sizeflag & DFLAG)
02953 *obufp++ = 'l';
02954 else
02955 *obufp++ = 'w';
02956 used_prefixes |= (prefixes & PREFIX_DATA);
02957 }
02958 }
02959 break;
02960 case 'X':
02961 if (prefixes & PREFIX_DATA)
02962 *obufp++ = 'd';
02963 else
02964 *obufp++ = 's';
02965 used_prefixes |= (prefixes & PREFIX_DATA);
02966 break;
02967 case 'Y':
02968 if (intel_syntax)
02969 break;
02970 if (rex & REX_MODE64)
02971 {
02972 USED_REX (REX_MODE64);
02973 *obufp++ = 'q';
02974 }
02975 break;
02976
02977 case 'W':
02978
02979 USED_REX (0);
02980 if (rex)
02981 *obufp++ = 'l';
02982 else if (sizeflag & DFLAG)
02983 *obufp++ = 'w';
02984 else
02985 *obufp++ = 'b';
02986 if (intel_syntax)
02987 {
02988 if (rex)
02989 {
02990 *obufp++ = 'q';
02991 *obufp++ = 'e';
02992 }
02993 if (sizeflag & DFLAG)
02994 {
02995 *obufp++ = 'd';
02996 *obufp++ = 'e';
02997 }
02998 else
02999 {
03000 *obufp++ = 'w';
03001 }
03002 }
03003 if (!rex)
03004 used_prefixes |= (prefixes & PREFIX_DATA);
03005 break;
03006 }
03007 alt = 0;
03008 }
03009 *obufp = 0;
03010 return 0;
03011 }
03012
03013 static void
03014 oappend (const char *s)
03015 {
03016 strcpy (obufp, s);
03017 obufp += strlen (s);
03018 }
03019
03020 static void
03021 append_seg (void)
03022 {
03023 if (prefixes & PREFIX_CS)
03024 {
03025 used_prefixes |= PREFIX_CS;
03026 oappend ("%cs:" + intel_syntax);
03027 }
03028 if (prefixes & PREFIX_DS)
03029 {
03030 used_prefixes |= PREFIX_DS;
03031 oappend ("%ds:" + intel_syntax);
03032 }
03033 if (prefixes & PREFIX_SS)
03034 {
03035 used_prefixes |= PREFIX_SS;
03036 oappend ("%ss:" + intel_syntax);
03037 }
03038 if (prefixes & PREFIX_ES)
03039 {
03040 used_prefixes |= PREFIX_ES;
03041 oappend ("%es:" + intel_syntax);
03042 }
03043 if (prefixes & PREFIX_FS)
03044 {
03045 used_prefixes |= PREFIX_FS;
03046 oappend ("%fs:" + intel_syntax);
03047 }
03048 if (prefixes & PREFIX_GS)
03049 {
03050 used_prefixes |= PREFIX_GS;
03051 oappend ("%gs:" + intel_syntax);
03052 }
03053 }
03054
03055 static void
03056 OP_indirE (int bytemode, int sizeflag)
03057 {
03058 if (!intel_syntax)
03059 oappend ("*");
03060 OP_E (bytemode, sizeflag);
03061 }
03062
03063 static void
03064 print_operand_value (char *buf, int hex, bfd_vma disp)
03065 {
03066 if (mode_64bit)
03067 {
03068 if (hex)
03069 {
03070 char tmp[30];
03071 int i;
03072 buf[0] = '0';
03073 buf[1] = 'x';
03074 sprintf_vma (tmp, disp);
03075 for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++);
03076 strcpy (buf + 2, tmp + i);
03077 }
03078 else
03079 {
03080 bfd_signed_vma v = disp;
03081 char tmp[30];
03082 int i;
03083 if (v < 0)
03084 {
03085 *(buf++) = '-';
03086 v = -disp;
03087
03088 if (v < 0)
03089 {
03090 strcpy (buf, "9223372036854775808");
03091 return;
03092 }
03093 }
03094 if (!v)
03095 {
03096 strcpy (buf, "0");
03097 return;
03098 }
03099
03100 i = 0;
03101 tmp[29] = 0;
03102 while (v)
03103 {
03104 tmp[28 - i] = (v % 10) + '0';
03105 v /= 10;
03106 i++;
03107 }
03108 strcpy (buf, tmp + 29 - i);
03109 }
03110 }
03111 else
03112 {
03113 if (hex)
03114 sprintf (buf, "0x%x", (unsigned int) disp);
03115 else
03116 sprintf (buf, "%d", (int) disp);
03117 }
03118 }
03119
03120 static void
03121 OP_E (int bytemode, int sizeflag)
03122 {
03123 bfd_vma disp;
03124 int add = 0;
03125 int riprel = 0;
03126 USED_REX (REX_EXTZ);
03127 if (rex & REX_EXTZ)
03128 add += 8;
03129
03130
03131 MODRM_CHECK;
03132 codep++;
03133
03134 if (mod == 3)
03135 {
03136 switch (bytemode)
03137 {
03138 case b_mode:
03139 USED_REX (0);
03140 if (rex)
03141 oappend (names8rex[rm + add]);
03142 else
03143 oappend (names8[rm + add]);
03144 break;
03145 case w_mode:
03146 oappend (names16[rm + add]);
03147 break;
03148 case d_mode:
03149 oappend (names32[rm + add]);
03150 break;
03151 case q_mode:
03152 oappend (names64[rm + add]);
03153 break;
03154 case m_mode:
03155 if (mode_64bit)
03156 oappend (names64[rm + add]);
03157 else
03158 oappend (names32[rm + add]);
03159 break;
03160 case v_mode:
03161 case dq_mode:
03162 case dqw_mode:
03163 USED_REX (REX_MODE64);
03164 if (rex & REX_MODE64)
03165 oappend (names64[rm + add]);
03166 else if ((sizeflag & DFLAG) || bytemode != v_mode)
03167 oappend (names32[rm + add]);
03168 else
03169 oappend (names16[rm + add]);
03170 used_prefixes |= (prefixes & PREFIX_DATA);
03171 break;
03172 case 0:
03173 break;
03174 default:
03175 oappend (INTERNAL_DISASSEMBLER_ERROR);
03176 break;
03177 }
03178 return;
03179 }
03180
03181 disp = 0;
03182 append_seg ();
03183
03184 if ((sizeflag & AFLAG) || mode_64bit)
03185 {
03186 int havesib;
03187 int havebase;
03188 int base;
03189 int index = 0;
03190 int scale = 0;
03191
03192 havesib = 0;
03193 havebase = 1;
03194 base = rm;
03195
03196 if (base == 4)
03197 {
03198 havesib = 1;
03199 FETCH_DATA (the_info, codep + 1);
03200 index = (*codep >> 3) & 7;
03201 if (mode_64bit || index != 0x4)
03202
03203 scale = (*codep >> 6) & 3;
03204 base = *codep & 7;
03205 USED_REX (REX_EXTY);
03206 USED_REX (REX_EXTZ);
03207 if (rex & REX_EXTY)
03208 index += 8;
03209 if (rex & REX_EXTZ)
03210 base += 8;
03211 codep++;
03212 }
03213
03214 switch (mod)
03215 {
03216 case 0:
03217 if ((base & 7) == 5)
03218 {
03219 havebase = 0;
03220 if (mode_64bit && !havesib)
03221 riprel = 1;
03222 disp = get32s ();
03223 }
03224 break;
03225 case 1:
03226 FETCH_DATA (the_info, codep + 1);
03227 disp = *codep++;
03228 if ((disp & 0x80) != 0)
03229 disp -= 0x100;
03230 break;
03231 case 2:
03232 disp = get32s ();
03233 break;
03234 }
03235
03236 if (!intel_syntax)
03237 if (mod != 0 || (base & 7) == 5)
03238 {
03239 print_operand_value (scratchbuf, !riprel, disp);
03240 oappend (scratchbuf);
03241 if (riprel)
03242 {
03243 set_op (disp, 1);
03244 oappend ("(%rip)");
03245 }
03246 }
03247
03248 if (havebase || (havesib && (index != 4 || scale != 0)))
03249 {
03250 if (intel_syntax)
03251 {
03252 switch (bytemode)
03253 {
03254 case b_mode:
03255 oappend ("BYTE PTR ");
03256 break;
03257 case w_mode:
03258 case dqw_mode:
03259 oappend ("WORD PTR ");
03260 break;
03261 case v_mode:
03262 case dq_mode:
03263 USED_REX (REX_MODE64);
03264 if (rex & REX_MODE64)
03265 oappend ("QWORD PTR ");
03266 else if ((sizeflag & DFLAG) || bytemode == dq_mode)
03267 oappend ("DWORD PTR ");
03268 else
03269 oappend ("WORD PTR ");
03270 used_prefixes |= (prefixes & PREFIX_DATA);
03271 break;
03272 case d_mode:
03273 oappend ("DWORD PTR ");
03274 break;
03275 case q_mode:
03276 oappend ("QWORD PTR ");
03277 break;
03278 case m_mode:
03279 if (mode_64bit)
03280 oappend ("QWORD PTR ");
03281 else
03282 oappend ("DWORD PTR ");
03283 break;
03284 case f_mode:
03285 if (sizeflag & DFLAG)
03286 {
03287 used_prefixes |= (prefixes & PREFIX_DATA);
03288 oappend ("FWORD PTR ");
03289 }
03290 else
03291 oappend ("DWORD PTR ");
03292 break;
03293 case t_mode:
03294 oappend ("TBYTE PTR ");
03295 break;
03296 case x_mode:
03297 oappend ("XMMWORD PTR ");
03298 break;
03299 default:
03300 break;
03301 }
03302 }
03303 *obufp++ = open_char;
03304 if (intel_syntax && riprel)
03305 oappend ("rip + ");
03306 *obufp = '\0';
03307 USED_REX (REX_EXTZ);
03308 if (!havesib && (rex & REX_EXTZ))
03309 base += 8;
03310 if (havebase)
03311 oappend (mode_64bit && (sizeflag & AFLAG)
03312 ? names64[base] : names32[base]);
03313 if (havesib)
03314 {
03315 if (index != 4)
03316 {
03317 if (!intel_syntax || havebase)
03318 {
03319 *obufp++ = separator_char;
03320 *obufp = '\0';
03321 }
03322 oappend (mode_64bit && (sizeflag & AFLAG)
03323 ? names64[index] : names32[index]);
03324 }
03325 if (scale != 0 || (!intel_syntax && index != 4))
03326 {
03327 *obufp++ = scale_char;
03328 *obufp = '\0';
03329 sprintf (scratchbuf, "%d", 1 << scale);
03330 oappend (scratchbuf);
03331 }
03332 }
03333 if (intel_syntax)
03334 if (mod != 0 || (base & 7) == 5)
03335 {
03336
03337 if (disp != 0)
03338 {
03339 if ((bfd_signed_vma) disp > 0)
03340 {
03341 *obufp++ = '+';
03342 *obufp = '\0';
03343 }
03344
03345 print_operand_value (scratchbuf, 0, disp);
03346 oappend (scratchbuf);
03347 }
03348 }
03349
03350 *obufp++ = close_char;
03351 *obufp = '\0';
03352 }
03353 else if (intel_syntax)
03354 {
03355 if (mod != 0 || (base & 7) == 5)
03356 {
03357 if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
03358 | PREFIX_ES | PREFIX_FS | PREFIX_GS))
03359 ;
03360 else
03361 {
03362 oappend (names_seg[ds_reg - es_reg]);
03363 oappend (":");
03364 }
03365 print_operand_value (scratchbuf, 1, disp);
03366 oappend (scratchbuf);
03367 }
03368 }
03369 }
03370 else
03371 {
03372 switch (mod)
03373 {
03374 case 0:
03375 if ((rm & 7) == 6)
03376 {
03377 disp = get16 ();
03378 if ((disp & 0x8000) != 0)
03379 disp -= 0x10000;
03380 }
03381 break;
03382 case 1:
03383 FETCH_DATA (the_info, codep + 1);
03384 disp = *codep++;
03385 if ((disp & 0x80) != 0)
03386 disp -= 0x100;
03387 break;
03388 case 2:
03389 disp = get16 ();
03390 if ((disp & 0x8000) != 0)
03391 disp -= 0x10000;
03392 break;
03393 }
03394
03395 if (!intel_syntax)
03396 if (mod != 0 || (rm & 7) == 6)
03397 {
03398 print_operand_value (scratchbuf, 0, disp);
03399 oappend (scratchbuf);
03400 }
03401
03402 if (mod != 0 || (rm & 7) != 6)
03403 {
03404 *obufp++ = open_char;
03405 *obufp = '\0';
03406 oappend (index16[rm + add]);
03407 *obufp++ = close_char;
03408 *obufp = '\0';
03409 }
03410 }
03411 }
03412
03413 static void
03414 OP_G (int bytemode, int sizeflag)
03415 {
03416 int add = 0;
03417 USED_REX (REX_EXTX);
03418 if (rex & REX_EXTX)
03419 add += 8;
03420 switch (bytemode)
03421 {
03422 case b_mode:
03423 USED_REX (0);
03424 if (rex)
03425 oappend (names8rex[reg + add]);
03426 else
03427 oappend (names8[reg + add]);
03428 break;
03429 case w_mode:
03430 oappend (names16[reg + add]);
03431 break;
03432 case d_mode:
03433 oappend (names32[reg + add]);
03434 break;
03435 case q_mode:
03436 oappend (names64[reg + add]);
03437 break;
03438 case v_mode:
03439 case dq_mode:
03440 case dqw_mode:
03441 USED_REX (REX_MODE64);
03442 if (rex & REX_MODE64)
03443 oappend (names64[reg + add]);
03444 else if ((sizeflag & DFLAG) || bytemode != v_mode)
03445 oappend (names32[reg + add]);
03446 else
03447 oappend (names16[reg + add]);
03448 used_prefixes |= (prefixes & PREFIX_DATA);
03449 break;
03450 default:
03451 oappend (INTERNAL_DISASSEMBLER_ERROR);
03452 break;
03453 }
03454 }
03455
03456 static bfd_vma
03457 get64 (void)
03458 {
03459 bfd_vma x;
03460 #ifdef BFD64
03461 unsigned int a;
03462 unsigned int b;
03463
03464 FETCH_DATA (the_info, codep + 8);
03465 a = *codep++ & 0xff;
03466 a |= (*codep++ & 0xff) << 8;
03467 a |= (*codep++ & 0xff) << 16;
03468 a |= (*codep++ & 0xff) << 24;
03469 b = *codep++ & 0xff;
03470 b |= (*codep++ & 0xff) << 8;
03471 b |= (*codep++ & 0xff) << 16;
03472 b |= (*codep++ & 0xff) << 24;
03473 x = a + ((bfd_vma) b << 32);
03474 #else
03475 abort ();
03476 x = 0;
03477 #endif
03478 return x;
03479 }
03480
03481 static bfd_signed_vma
03482 get32 (void)
03483 {
03484 bfd_signed_vma x = 0;
03485
03486 FETCH_DATA (the_info, codep + 4);
03487 x = *codep++ & (bfd_signed_vma) 0xff;
03488 x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
03489 x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
03490 x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
03491 return x;
03492 }
03493
03494 static bfd_signed_vma
03495 get32s (void)
03496 {
03497 bfd_signed_vma x = 0;
03498
03499 FETCH_DATA (the_info, codep + 4);
03500 x = *codep++ & (bfd_signed_vma) 0xff;
03501 x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
03502 x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
03503 x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
03504
03505 x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
03506
03507 return x;
03508 }
03509
03510 static int
03511 get16 (void)
03512 {
03513 int x = 0;
03514
03515 FETCH_DATA (the_info, codep + 2);
03516 x = *codep++ & 0xff;
03517 x |= (*codep++ & 0xff) << 8;
03518 return x;
03519 }
03520
03521 static void
03522 set_op (bfd_vma op, int riprel)
03523 {
03524 op_index[op_ad] = op_ad;
03525 if (mode_64bit)
03526 {
03527 op_address[op_ad] = op;
03528 op_riprel[op_ad] = riprel;
03529 }
03530 else
03531 {
03532
03533 op_address[op_ad] = op & 0xffffffff;
03534 op_riprel[op_ad] = riprel & 0xffffffff;
03535 }
03536 }
03537
03538 static void
03539 OP_REG (int code, int sizeflag)
03540 {
03541 const char *s;
03542 int add = 0;
03543 USED_REX (REX_EXTZ);
03544 if (rex & REX_EXTZ)
03545 add = 8;
03546
03547 switch (code)
03548 {
03549 case indir_dx_reg:
03550 if (intel_syntax)
03551 s = "[dx]";
03552 else
03553 s = "(%dx)";
03554 break;
03555 case ax_reg: case cx_reg: case dx_reg: case bx_reg:
03556 case sp_reg: case bp_reg: case si_reg: case di_reg:
03557 s = names16[code - ax_reg + add];
03558 break;
03559 case es_reg: case ss_reg: case cs_reg:
03560 case ds_reg: case fs_reg: case gs_reg:
03561 s = names_seg[code - es_reg + add];
03562 break;
03563 case al_reg: case ah_reg: case cl_reg: case ch_reg:
03564 case dl_reg: case dh_reg: case bl_reg: case bh_reg:
03565 USED_REX (0);
03566 if (rex)
03567 s = names8rex[code - al_reg + add];
03568 else
03569 s = names8[code - al_reg];
03570 break;
03571 case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
03572 case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
03573 if (mode_64bit)
03574 {
03575 s = names64[code - rAX_reg + add];
03576 break;
03577 }
03578 code += eAX_reg - rAX_reg;
03579
03580 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
03581 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
03582 USED_REX (REX_MODE64);
03583 if (rex & REX_MODE64)
03584 s = names64[code - eAX_reg + add];
03585 else if (sizeflag & DFLAG)
03586 s = names32[code - eAX_reg + add];
03587 else
03588 s = names16[code - eAX_reg + add];
03589 used_prefixes |= (prefixes & PREFIX_DATA);
03590 break;
03591 default:
03592 s = INTERNAL_DISASSEMBLER_ERROR;
03593 break;
03594 }
03595 oappend (s);
03596 }
03597
03598 static void
03599 OP_IMREG (int code, int sizeflag)
03600 {
03601 const char *s;
03602
03603 switch (code)
03604 {
03605 case indir_dx_reg:
03606 if (intel_syntax)
03607 s = "[dx]";
03608 else
03609 s = "(%dx)";
03610 break;
03611 case ax_reg: case cx_reg: case dx_reg: case bx_reg:
03612 case sp_reg: case bp_reg: case si_reg: case di_reg:
03613 s = names16[code - ax_reg];
03614 break;
03615 case es_reg: case ss_reg: case cs_reg:
03616 case ds_reg: case fs_reg: case gs_reg:
03617 s = names_seg[code - es_reg];
03618 break;
03619 case al_reg: case ah_reg: case cl_reg: case ch_reg:
03620 case dl_reg: case dh_reg: case bl_reg: case bh_reg:
03621 USED_REX (0);
03622 if (rex)
03623 s = names8rex[code - al_reg];
03624 else
03625 s = names8[code - al_reg];
03626 break;
03627 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
03628 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
03629 USED_REX (REX_MODE64);
03630 if (rex & REX_MODE64)
03631 s = names64[code - eAX_reg];
03632 else if (sizeflag & DFLAG)
03633 s = names32[code - eAX_reg];
03634 else
03635 s = names16[code - eAX_reg];
03636 used_prefixes |= (prefixes & PREFIX_DATA);
03637 break;
03638 default:
03639 s = INTERNAL_DISASSEMBLER_ERROR;
03640 break;
03641 }
03642 oappend (s);
03643 }
03644
03645 static void
03646 OP_I (int bytemode, int sizeflag)
03647 {
03648 bfd_signed_vma op;
03649 bfd_signed_vma mask = -1;
03650
03651 switch (bytemode)
03652 {
03653 case b_mode:
03654 FETCH_DATA (the_info, codep + 1);
03655 op = *codep++;
03656 mask = 0xff;
03657 break;
03658 case q_mode:
03659 if (mode_64bit)
03660 {
03661 op = get32s ();
03662 break;
03663 }
03664
03665 case v_mode:
03666 USED_REX (REX_MODE64);
03667 if (rex & REX_MODE64)
03668 op = get32s ();
03669 else if (sizeflag & DFLAG)
03670 {
03671 op = get32 ();
03672 mask = 0xffffffff;
03673 }
03674 else
03675 {
03676 op = get16 ();
03677 mask = 0xfffff;
03678 }
03679 used_prefixes |= (prefixes & PREFIX_DATA);
03680 break;
03681 case w_mode:
03682 mask = 0xfffff;
03683 op = get16 ();
03684 break;
03685 case const_1_mode:
03686 if (intel_syntax)
03687 oappend ("1");
03688 return;
03689 default:
03690 oappend (INTERNAL_DISASSEMBLER_ERROR);
03691 return;
03692 }
03693
03694 op &= mask;
03695 scratchbuf[0] = '$';
03696 print_operand_value (scratchbuf + 1, 1, op);
03697 oappend (scratchbuf + intel_syntax);
03698 scratchbuf[0] = '\0';
03699 }
03700
03701 static void
03702 OP_I64 (int bytemode, int sizeflag)
03703 {
03704 bfd_signed_vma op;
03705 bfd_signed_vma mask = -1;
03706
03707 if (!mode_64bit)
03708 {
03709 OP_I (bytemode, sizeflag);
03710 return;
03711 }
03712
03713 switch (bytemode)
03714 {
03715 case b_mode:
03716 FETCH_DATA (the_info, codep + 1);
03717 op = *codep++;
03718 mask = 0xff;
03719 break;
03720 case v_mode:
03721 USED_REX (REX_MODE64);
03722 if (rex & REX_MODE64)
03723 op = get64 ();
03724 else if (sizeflag & DFLAG)
03725 {
03726 op = get32 ();
03727 mask = 0xffffffff;
03728 }
03729 else
03730 {
03731 op = get16 ();
03732 mask = 0xfffff;
03733 }
03734 used_prefixes |= (prefixes & PREFIX_DATA);
03735 break;
03736 case w_mode:
03737 mask = 0xfffff;
03738 op = get16 ();
03739 break;
03740 default:
03741 oappend (INTERNAL_DISASSEMBLER_ERROR);
03742 return;
03743 }
03744
03745 op &= mask;
03746 scratchbuf[0] = '$';
03747 print_operand_value (scratchbuf + 1, 1, op);
03748 oappend (scratchbuf + intel_syntax);
03749 scratchbuf[0] = '\0';
03750 }
03751
03752 static void
03753 OP_sI (int bytemode, int sizeflag)
03754 {
03755 bfd_signed_vma op;
03756 bfd_signed_vma mask = -1;
03757
03758 switch (bytemode)
03759 {
03760 case b_mode:
03761 FETCH_DATA (the_info, codep + 1);
03762 op = *codep++;
03763 if ((op & 0x80) != 0)
03764 op -= 0x100;
03765 mask = 0xffffffff;
03766 break;
03767 case v_mode:
03768 USED_REX (REX_MODE64);
03769 if (rex & REX_MODE64)
03770 op = get32s ();
03771 else if (sizeflag & DFLAG)
03772 {
03773 op = get32s ();
03774 mask = 0xffffffff;
03775 }
03776 else
03777 {
03778 mask = 0xffffffff;
03779 op = get16 ();
03780 if ((op & 0x8000) != 0)
03781 op -= 0x10000;
03782 }
03783 used_prefixes |= (prefixes & PREFIX_DATA);
03784 break;
03785 case w_mode:
03786 op = get16 ();
03787 mask = 0xffffffff;
03788 if ((op & 0x8000) != 0)
03789 op -= 0x10000;
03790 break;
03791 default:
03792 oappend (INTERNAL_DISASSEMBLER_ERROR);
03793 return;
03794 }
03795
03796 scratchbuf[0] = '$';
03797 print_operand_value (scratchbuf + 1, 1, op);
03798 oappend (scratchbuf + intel_syntax);
03799 }
03800
03801 static void
03802 OP_J (int bytemode, int sizeflag)
03803 {
03804 bfd_vma disp;
03805 bfd_vma mask = -1;
03806
03807 switch (bytemode)
03808 {
03809 case b_mode:
03810 FETCH_DATA (the_info, codep + 1);
03811 disp = *codep++;
03812 if ((disp & 0x80) != 0)
03813 disp -= 0x100;
03814 break;
03815 case v_mode:
03816 if (sizeflag & DFLAG)
03817 disp = get32s ();
03818 else
03819 {
03820 disp = get16 ();
03821
03822
03823
03824 mask = 0xffff;
03825 }
03826 break;
03827 default:
03828 oappend (INTERNAL_DISASSEMBLER_ERROR);
03829 return;
03830 }
03831 disp = (start_pc + codep - start_codep + disp) & mask;
03832 set_op (disp, 0);
03833 print_operand_value (scratchbuf, 1, disp);
03834 oappend (scratchbuf);
03835 }
03836
03837 static void
03838 OP_SEG (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
03839 {
03840 oappend (names_seg[reg]);
03841 }
03842
03843 static void
03844 OP_DIR (int dummy ATTRIBUTE_UNUSED, int sizeflag)
03845 {
03846 int seg, offset;
03847
03848 if (sizeflag & DFLAG)
03849 {
03850 offset = get32 ();
03851 seg = get16 ();
03852 }
03853 else
03854 {
03855 offset = get16 ();
03856 seg = get16 ();
03857 }
03858 used_prefixes |= (prefixes & PREFIX_DATA);
03859 if (intel_syntax)
03860 sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
03861 else
03862 sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
03863 oappend (scratchbuf);
03864 }
03865
03866 static void
03867 OP_OFF (int bytemode ATTRIBUTE_UNUSED, int sizeflag)
03868 {
03869 bfd_vma off;
03870
03871 append_seg ();
03872
03873 if ((sizeflag & AFLAG) || mode_64bit)
03874 off = get32 ();
03875 else
03876 off = get16 ();
03877
03878 if (intel_syntax)
03879 {
03880 if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
03881 | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
03882 {
03883 oappend (names_seg[ds_reg - es_reg]);
03884 oappend (":");
03885 }
03886 }
03887 print_operand_value (scratchbuf, 1, off);
03888 oappend (scratchbuf);
03889 }
03890
03891 static void
03892 OP_OFF64 (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
03893 {
03894 bfd_vma off;
03895
03896 if (!mode_64bit)
03897 {
03898 OP_OFF (bytemode, sizeflag);
03899 return;
03900 }
03901
03902 append_seg ();
03903
03904 off = get64 ();
03905
03906 if (intel_syntax)
03907 {
03908 if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
03909 | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
03910 {
03911 oappend (names_seg[ds_reg - es_reg]);
03912 oappend (":");
03913 }
03914 }
03915 print_operand_value (scratchbuf, 1, off);
03916 oappend (scratchbuf);
03917 }
03918
03919 static void
03920 ptr_reg (int code, int sizeflag)
03921 {
03922 const char *s;
03923
03924 *obufp++ = open_char;
03925 used_prefixes |= (prefixes & PREFIX_ADDR);
03926 if (mode_64bit)
03927 {
03928 if (!(sizeflag & AFLAG))
03929 s = names32[code - eAX_reg];
03930 else
03931 s = names64[code - eAX_reg];
03932 }
03933 else if (sizeflag & AFLAG)
03934 s = names32[code - eAX_reg];
03935 else
03936 s = names16[code - eAX_reg];
03937 oappend (s);
03938 *obufp++ = close_char;
03939 *obufp = 0;
03940 }
03941
03942 static void
03943 OP_ESreg (int code, int sizeflag)
03944 {
03945 if (intel_syntax)
03946 {
03947 if (codep[-1] & 1)
03948 {
03949 USED_REX (REX_MODE64);
03950 used_prefixes |= (prefixes & PREFIX_DATA);
03951 if (rex & REX_MODE64)
03952 oappend ("QWORD PTR ");
03953 else if ((sizeflag & DFLAG))
03954 oappend ("DWORD PTR ");
03955 else
03956 oappend ("WORD PTR ");
03957 }
03958 else
03959 oappend ("BYTE PTR ");
03960 }
03961
03962 oappend ("%es:" + intel_syntax);
03963 ptr_reg (code, sizeflag);
03964 }
03965
03966 static void
03967 OP_DSreg (int code, int sizeflag)
03968 {
03969 if (intel_syntax)
03970 {
03971 if (codep[-1] != 0xd7 && (codep[-1] & 1))
03972 {
03973 USED_REX (REX_MODE64);
03974 used_prefixes |= (prefixes & PREFIX_DATA);
03975 if (rex & REX_MODE64)
03976 oappend ("QWORD PTR ");
03977 else if ((sizeflag & DFLAG))
03978 oappend ("DWORD PTR ");
03979 else
03980 oappend ("WORD PTR ");
03981 }
03982 else
03983 oappend ("BYTE PTR ");
03984 }
03985
03986 if ((prefixes
03987 & (PREFIX_CS
03988 | PREFIX_DS
03989 | PREFIX_SS
03990 | PREFIX_ES
03991 | PREFIX_FS
03992 | PREFIX_GS)) == 0)
03993 prefixes |= PREFIX_DS;
03994 append_seg ();
03995 ptr_reg (code, sizeflag);
03996 }
03997
03998 static void
03999 OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
04000 {
04001 int add = 0;
04002 if (rex & REX_EXTX)
04003 {
04004 USED_REX (REX_EXTX);
04005 add = 8;
04006 }
04007 else if (!mode_64bit && (prefixes & PREFIX_LOCK))
04008 {
04009 used_prefixes |= PREFIX_LOCK;
04010 add = 8;
04011 }
04012 sprintf (scratchbuf, "%%cr%d", reg + add);
04013 oappend (scratchbuf + intel_syntax);
04014 }
04015
04016 static void
04017 OP_D (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
04018 {
04019 int add = 0;
04020 USED_REX (REX_EXTX);
04021 if (rex & REX_EXTX)
04022 add = 8;
04023 if (intel_syntax)
04024 sprintf (scratchbuf, "db%d", reg + add);
04025 else
04026 sprintf (scratchbuf, "%%db%d", reg + add);
04027 oappend (scratchbuf);
04028 }
04029
04030 static void
04031 OP_T (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
04032 {
04033 sprintf (scratchbuf, "%%tr%d", reg);
04034 oappend (scratchbuf + intel_syntax);
04035 }
04036
04037 static void
04038 OP_Rd (int bytemode, int sizeflag)
04039 {
04040 if (mod == 3)
04041 OP_E (bytemode, sizeflag);
04042 else
04043 BadOp ();
04044 }
04045
04046 static void
04047 OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
04048 {
04049 used_prefixes |= (prefixes & PREFIX_DATA);
04050 if (prefixes & PREFIX_DATA)
04051 {
04052 int add = 0;
04053 USED_REX (REX_EXTX);
04054 if (rex & REX_EXTX)
04055 add = 8;
04056 sprintf (scratchbuf, "%%xmm%d", reg + add);
04057 }
04058 else
04059 sprintf (scratchbuf, "%%mm%d", reg);
04060 oappend (scratchbuf + intel_syntax);
04061 }
04062
04063 static void
04064 OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
04065 {
04066 int add = 0;
04067 USED_REX (REX_EXTX);
04068 if (rex & REX_EXTX)
04069 add = 8;
04070 sprintf (scratchbuf, "%%xmm%d", reg + add);
04071 oappend (scratchbuf + intel_syntax);
04072 }
04073
04074 static void
04075 OP_EM (int bytemode, int sizeflag)
04076 {
04077 if (mod != 3)
04078 {
04079 if (intel_syntax && bytemode == v_mode)
04080 {
04081 bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode;
04082 used_prefixes |= (prefixes & PREFIX_DATA);
04083 }
04084 OP_E (bytemode, sizeflag);
04085 return;
04086 }
04087
04088
04089 MODRM_CHECK;
04090 codep++;
04091 used_prefixes |= (prefixes & PREFIX_DATA);
04092 if (prefixes & PREFIX_DATA)
04093 {
04094 int add = 0;
04095
04096 USED_REX (REX_EXTZ);
04097 if (rex & REX_EXTZ)
04098 add = 8;
04099 sprintf (scratchbuf, "%%xmm%d", rm + add);
04100 }
04101 else
04102 sprintf (scratchbuf, "%%mm%d", rm);
04103 oappend (scratchbuf + intel_syntax);
04104 }
04105
04106 static void
04107 OP_EX (int bytemode, int sizeflag)
04108 {
04109 int add = 0;
04110 if (mod != 3)
04111 {
04112 if (intel_syntax && bytemode == v_mode)
04113 {
04114 switch (prefixes & (PREFIX_DATA|PREFIX_REPZ|PREFIX_REPNZ))
04115 {
04116 case 0: bytemode = x_mode; break;
04117 case PREFIX_REPZ: bytemode = d_mode; used_prefixes |= PREFIX_REPZ; break;
04118 case PREFIX_DATA: bytemode = x_mode; used_prefixes |= PREFIX_DATA; break;
04119 case PREFIX_REPNZ: bytemode = q_mode; used_prefixes |= PREFIX_REPNZ; break;
04120 default: bytemode = 0; break;
04121 }
04122 }
04123 OP_E (bytemode, sizeflag);
04124 return;
04125 }
04126 USED_REX (REX_EXTZ);
04127 if (rex & REX_EXTZ)
04128 add = 8;
04129
04130
04131 MODRM_CHECK;
04132 codep++;
04133 sprintf (scratchbuf, "%%xmm%d", rm + add);
04134 oappend (scratchbuf + intel_syntax);
04135 }
04136
04137 static void
04138 OP_MS (int bytemode, int sizeflag)
04139 {
04140 if (mod == 3)
04141 OP_EM (bytemode, sizeflag);
04142 else
04143 BadOp ();
04144 }
04145
04146 static void
04147 OP_XS (int bytemode, int sizeflag)
04148 {
04149 if (mod == 3)
04150 OP_EX (bytemode, sizeflag);
04151 else
04152 BadOp ();
04153 }
04154
04155 static void
04156 OP_M (int bytemode, int sizeflag)
04157 {
04158 if (mod == 3)
04159 BadOp ();
04160 else
04161 OP_E (bytemode, sizeflag);
04162 }
04163
04164 static void
04165 OP_0f07 (int bytemode, int sizeflag)
04166 {
04167 if (mod != 3 || rm != 0)
04168 BadOp ();
04169 else
04170 OP_E (bytemode, sizeflag);
04171 }
04172
04173 static void
04174 OP_0fae (int bytemode, int sizeflag)
04175 {
04176 if (mod == 3)
04177 {
04178 if (reg == 7)
04179 strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
04180
04181 if (reg < 5 || rm != 0)
04182 {
04183 BadOp ();
04184 return;
04185 }
04186 }
04187 else if (reg != 7)
04188 {
04189 BadOp ();
04190 return;
04191 }
04192
04193 OP_E (bytemode, sizeflag);
04194 }
04195
04196 static void
04197 NOP_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
04198 {
04199
04200 if (prefixes == PREFIX_REPZ)
04201 strcpy (obuf, "pause");
04202 }
04203
04204 static const char *const Suffix3DNow[] = {
04205 NULL, NULL, NULL, NULL,
04206 NULL, NULL, NULL, NULL,
04207 NULL, NULL, NULL, NULL,
04208 "pi2fw", "pi2fd", NULL, NULL,
04209 NULL, NULL, NULL, NULL,
04210 NULL, NULL, NULL, NULL,
04211 NULL, NULL, NULL, NULL,
04212 "pf2iw", "pf2id", NULL, NULL,
04213 NULL, NULL, NULL, NULL,
04214 NULL, NULL, NULL, NULL,
04215 NULL, NULL, NULL, NULL,
04216 NULL, NULL, NULL, NULL,
04217 NULL, NULL, NULL, NULL,
04218 NULL, NULL, NULL, NULL,
04219 NULL, NULL, NULL, NULL,
04220 NULL, NULL, NULL, NULL,
04221 NULL, NULL, NULL, NULL,
04222 NULL, NULL, NULL, NULL,
04223 NULL, NULL, NULL, NULL,
04224 NULL, NULL, NULL, NULL,
04225 NULL, NULL, NULL, NULL,
04226 NULL, NULL, NULL, NULL,
04227 NULL, NULL, NULL, NULL,
04228 NULL, NULL, NULL, NULL,
04229 NULL, NULL, NULL, NULL,
04230 NULL, NULL, NULL, NULL,
04231 NULL, NULL, NULL, NULL,
04232 NULL, NULL, NULL, NULL,
04233 NULL, NULL, NULL, NULL,
04234 NULL, NULL, NULL, NULL,
04235 NULL, NULL, NULL, NULL,
04236 NULL, NULL, NULL, NULL,
04237 NULL, NULL, NULL, NULL,
04238 NULL, NULL, NULL, NULL,
04239 NULL, NULL, "pfnacc", NULL,
04240 NULL, NULL, "pfpnacc", NULL,
04241 "pfcmpge", NULL, NULL, NULL,
04242 "pfmin", NULL, "pfrcp", "pfrsqrt",
04243 NULL, NULL, "pfsub", NULL,
04244 NULL, NULL, "pfadd", NULL,
04245 "pfcmpgt", NULL, NULL, NULL,
04246 "pfmax", NULL, "pfrcpit1", "pfrsqit1",
04247 NULL, NULL, "pfsubr", NULL,
04248 NULL, NULL, "pfacc", NULL,
04249 "pfcmpeq", NULL, NULL, NULL,
04250 "pfmul", NULL, "pfrcpit2", "pfmulhrw",
04251 NULL, NULL, NULL, "pswapd",
04252 NULL, NULL, NULL, "pavgusb",
04253 NULL, NULL, NULL, NULL,
04254 NULL, NULL, NULL, NULL,
04255 NULL, NULL, NULL, NULL,
04256 NULL, NULL, NULL, NULL,
04257 NULL, NULL, NULL, NULL,
04258 NULL, NULL, NULL, NULL,
04259 NULL, NULL, NULL, NULL,
04260 NULL, NULL, NULL, NULL,
04261 NULL, NULL, NULL, NULL,
04262 NULL, NULL, NULL, NULL,
04263 NULL, NULL, NULL, NULL,
04264 NULL, NULL, NULL, NULL,
04265 NULL, NULL, NULL, NULL,
04266 NULL, NULL, NULL, NULL,
04267 NULL, NULL, NULL, NULL,
04268 NULL, NULL, NULL, NULL,
04269 };
04270
04271 static void
04272 OP_3DNowSuffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
04273 {
04274 const char *mnemonic;
04275
04276 FETCH_DATA (the_info, codep + 1);
04277
04278
04279
04280 obufp = obuf + strlen (obuf);
04281 mnemonic = Suffix3DNow[*codep++ & 0xff];
04282 if (mnemonic)
04283 oappend (mnemonic);
04284 else
04285 {
04286
04287
04288
04289
04290 op1out[0] = '\0';
04291 op2out[0] = '\0';
04292 BadOp ();
04293 }
04294 }
04295
04296 static const char *simd_cmp_op[] = {
04297 "eq",
04298 "lt",
04299 "le",
04300 "unord",
04301 "neq",
04302 "nlt",
04303 "nle",
04304 "ord"
04305 };
04306
04307 static void
04308 OP_SIMD_Suffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
04309 {
04310 unsigned int cmp_type;
04311
04312 FETCH_DATA (the_info, codep + 1);
04313 obufp = obuf + strlen (obuf);
04314 cmp_type = *codep++ & 0xff;
04315 if (cmp_type < 8)
04316 {
04317 char suffix1 = 'p', suffix2 = 's';
04318 used_prefixes |= (prefixes & PREFIX_REPZ);
04319 if (prefixes & PREFIX_REPZ)
04320 suffix1 = 's';
04321 else
04322 {
04323 used_prefixes |= (prefixes & PREFIX_DATA);
04324 if (prefixes & PREFIX_DATA)
04325 suffix2 = 'd';
04326 else
04327 {
04328 used_prefixes |= (prefixes & PREFIX_REPNZ);
04329 if (prefixes & PREFIX_REPNZ)
04330 suffix1 = 's', suffix2 = 'd';
04331 }
04332 }
04333 sprintf (scratchbuf, "cmp%s%c%c",
04334 simd_cmp_op[cmp_type], suffix1, suffix2);
04335 used_prefixes |= (prefixes & PREFIX_REPZ);
04336 oappend (scratchbuf);
04337 }
04338 else
04339 {
04340
04341 op1out[0] = '\0';
04342 op2out[0] = '\0';
04343 BadOp ();
04344 }
04345 }
04346
04347 static void
04348 SIMD_Fixup (int extrachar, int sizeflag ATTRIBUTE_UNUSED)
04349 {
04350
04351
04352 if (mod == 3)
04353 {
04354 char *p = obuf + strlen (obuf);
04355 *(p + 1) = '\0';
04356 *p = *(p - 1);
04357 *(p - 1) = *(p - 2);
04358 *(p - 2) = *(p - 3);
04359 *(p - 3) = extrachar;
04360 }
04361 }
04362
04363 static void
04364 PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
04365 {
04366 if (mod == 3 && reg == 1 && rm <= 1)
04367 {
04368
04369 char *p = obuf + strlen (obuf) - 4;
04370
04371
04372 if (*p == 'i')
04373 --p;
04374
04375 if (rm)
04376 {
04377
04378 strcpy (p, "mwait");
04379 if (!intel_syntax)
04380 strcpy (op1out, names32[0]);
04381 }
04382 else
04383 {
04384
04385 strcpy (p, "monitor");
04386 if (!intel_syntax)
04387 {
04388 if (!mode_64bit)
04389 strcpy (op1out, names32[0]);
04390 else if (!(prefixes & PREFIX_ADDR))
04391 strcpy (op1out, names64[0]);
04392 else
04393 {
04394 strcpy (op1out, names32[0]);
04395 used_prefixes |= PREFIX_ADDR;
04396 }
04397 strcpy (op3out, names32[2]);
04398 }
04399 }
04400 if (!intel_syntax)
04401 {
04402 strcpy (op2out, names32[1]);
04403 two_source_ops = 1;
04404 }
04405
04406 codep++;
04407 }
04408 else
04409 OP_E (0, sizeflag);
04410 }
04411
04412 static void
04413 INVLPG_Fixup (int bytemode, int sizeflag)
04414 {
04415 const char *alt;
04416
04417 switch (*codep)
04418 {
04419 case 0xf8:
04420 alt = "swapgs";
04421 break;
04422 case 0xf9:
04423 alt = "rdtscp";
04424 break;
04425 default:
04426 OP_E (bytemode, sizeflag);
04427 return;
04428 }
04429
04430 strcpy (obuf + strlen (obuf) - 6, alt);
04431 codep++;
04432 }
04433
04434 static void
04435 BadOp (void)
04436 {
04437
04438 codep = insn_codep + 1;
04439 oappend ("(bad)");
04440 }