Thu Dec 3 14:26:20 1998 Dave Brolley <brolley@cygnus.com>
[deliverable/binutils-gdb.git] / opcodes / i386-dis.c
CommitLineData
5d0734a7 1/* Print i386 instructions for GDB, the GNU debugger.
409595b8 2 Copyright (C) 1988, 89, 91, 93, 94, 95, 96, 97, 1998
41b96d55 3 Free Software Foundation, Inc.
5d0734a7
JK
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
726257a8 19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
5d0734a7
JK
20
21/*
22 * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
23 * July 1988
24 * modified by John Hassey (hassey@dg-rtp.dg.com)
25 */
26
27/*
28 * The main tables describing the instructions is essentially a copy
29 * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
30 * Programmers Manual. Usually, there is a capital letter, followed
31 * by a small letter. The capital letter tell the addressing mode,
32 * and the small letter tells about the operand size. Refer to
33 * the Intel manual for details.
34 */
35
36#include "dis-asm.h"
726257a8 37#include "sysdep.h"
80119c9e 38#include "opintl.h"
5d0734a7
JK
39
40#define MAXLEN 20
41
42#include <setjmp.h>
43
80119c9e
ILT
44#ifndef UNIXWARE_COMPAT
45/* Set non-zero for broken, compatible instructions. Set to zero for
46 non-broken opcodes. */
47#define UNIXWARE_COMPAT 1
48#endif
49
50
41b96d55
ILT
51static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
52
726257a8 53struct dis_private
5d0734a7
JK
54{
55 /* Points to first byte not fetched. */
56 bfd_byte *max_fetched;
57 bfd_byte the_buffer[MAXLEN];
58 bfd_vma insn_start;
59 jmp_buf bailout;
60};
61
62/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
63 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
64 on error. */
65#define FETCH_DATA(info, addr) \
726257a8 66 ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \
5d0734a7
JK
67 ? 1 : fetch_data ((info), (addr)))
68
69static int
70fetch_data (info, addr)
71 struct disassemble_info *info;
72 bfd_byte *addr;
73{
74 int status;
726257a8 75 struct dis_private *priv = (struct dis_private *)info->private_data;
5d0734a7
JK
76 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
77
78 status = (*info->read_memory_func) (start,
79 priv->max_fetched,
80 addr - priv->max_fetched,
81 info);
82 if (status != 0)
83 {
84 (*info->memory_error_func) (status, start, info);
05545edc 85 longjmp (priv->bailout, 1);
5d0734a7
JK
86 }
87 else
88 priv->max_fetched = addr;
89 return 1;
90}
91
92#define Eb OP_E, b_mode
93#define indirEb OP_indirE, b_mode
94#define Gb OP_G, b_mode
95#define Ev OP_E, v_mode
96#define indirEv OP_indirE, v_mode
97#define Ew OP_E, w_mode
98#define Ma OP_E, v_mode
99#define M OP_E, 0
100#define Mp OP_E, 0 /* ? */
101#define Gv OP_G, v_mode
102#define Gw OP_G, w_mode
103#define Rw OP_rm, w_mode
104#define Rd OP_rm, d_mode
105#define Ib OP_I, b_mode
106#define sIb OP_sI, b_mode /* sign extened byte */
107#define Iv OP_I, v_mode
108#define Iw OP_I, w_mode
109#define Jb OP_J, b_mode
110#define Jv OP_J, v_mode
41b96d55 111#if 0
5d0734a7 112#define ONE OP_ONE, 0
41b96d55 113#endif
5d0734a7
JK
114#define Cd OP_C, d_mode
115#define Dd OP_D, d_mode
116#define Td OP_T, d_mode
117
118#define eAX OP_REG, eAX_reg
119#define eBX OP_REG, eBX_reg
120#define eCX OP_REG, eCX_reg
121#define eDX OP_REG, eDX_reg
122#define eSP OP_REG, eSP_reg
123#define eBP OP_REG, eBP_reg
124#define eSI OP_REG, eSI_reg
125#define eDI OP_REG, eDI_reg
126#define AL OP_REG, al_reg
127#define CL OP_REG, cl_reg
128#define DL OP_REG, dl_reg
129#define BL OP_REG, bl_reg
130#define AH OP_REG, ah_reg
131#define CH OP_REG, ch_reg
132#define DH OP_REG, dh_reg
133#define BH OP_REG, bh_reg
134#define AX OP_REG, ax_reg
135#define DX OP_REG, dx_reg
136#define indirDX OP_REG, indir_dx_reg
137
138#define Sw OP_SEG, w_mode
139#define Ap OP_DIR, lptr
140#define Av OP_DIR, v_mode
141#define Ob OP_OFF, b_mode
142#define Ov OP_OFF, v_mode
80119c9e
ILT
143#define Xb OP_DSreg, eSI_reg
144#define Xv OP_DSreg, eSI_reg
145#define Yb OP_ESreg, eDI_reg
146#define Yv OP_ESreg, eDI_reg
147#define DSBX OP_DSreg, eBX_reg
5d0734a7
JK
148
149#define es OP_REG, es_reg
150#define ss OP_REG, ss_reg
151#define cs OP_REG, cs_reg
152#define ds OP_REG, ds_reg
153#define fs OP_REG, fs_reg
154#define gs OP_REG, gs_reg
155
eedca9da
ILT
156#define MX OP_MMX, 0
157#define EM OP_EM, v_mode
158#define MS OP_MS, b_mode
159
80119c9e 160/* bits in sizeflag */
5f90dab1
ILT
161#if 0 /* leave undefined until someone adds the extra flag to objdump */
162#define SUFFIX_ALWAYS 4
163#endif
80119c9e
ILT
164#define AFLAG 2
165#define DFLAG 1
166
167typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag));
168
169static void OP_E PARAMS ((int, int));
170static void OP_G PARAMS ((int, int));
171static void OP_I PARAMS ((int, int));
172static void OP_indirE PARAMS ((int, int));
173static void OP_sI PARAMS ((int, int));
174static void OP_REG PARAMS ((int, int));
175static void OP_J PARAMS ((int, int));
176static void OP_DIR PARAMS ((int, int));
177static void OP_OFF PARAMS ((int, int));
178static void OP_ESreg PARAMS ((int, int));
179static void OP_DSreg PARAMS ((int, int));
180static void OP_SEG PARAMS ((int, int));
181static void OP_C PARAMS ((int, int));
182static void OP_D PARAMS ((int, int));
183static void OP_T PARAMS ((int, int));
184static void OP_rm PARAMS ((int, int));
185static void OP_ST PARAMS ((int, int));
186static void OP_STi PARAMS ((int, int));
41b96d55 187#if 0
80119c9e 188static void OP_ONE PARAMS ((int, int));
41b96d55 189#endif
80119c9e
ILT
190static void OP_MMX PARAMS ((int, int));
191static void OP_EM PARAMS ((int, int));
192static void OP_MS PARAMS ((int, int));
be0c8b05 193
80119c9e 194static void append_seg PARAMS ((void));
80ade993 195static void set_op PARAMS ((unsigned int op));
80119c9e
ILT
196static void putop PARAMS ((char *template, int sizeflag));
197static void dofloat PARAMS ((int sizeflag));
be0c8b05
SG
198static int get16 PARAMS ((void));
199static int get32 PARAMS ((void));
200static void ckprefix PARAMS ((void));
80119c9e 201static void ptr_reg PARAMS ((int, int));
5d0734a7
JK
202
203#define b_mode 1
204#define v_mode 2
205#define w_mode 3
206#define d_mode 4
207
208#define es_reg 100
209#define cs_reg 101
210#define ss_reg 102
211#define ds_reg 103
212#define fs_reg 104
213#define gs_reg 105
214#define eAX_reg 107
215#define eCX_reg 108
216#define eDX_reg 109
217#define eBX_reg 110
218#define eSP_reg 111
219#define eBP_reg 112
220#define eSI_reg 113
221#define eDI_reg 114
222
223#define lptr 115
224
225#define al_reg 116
226#define cl_reg 117
227#define dl_reg 118
228#define bl_reg 119
229#define ah_reg 120
230#define ch_reg 121
231#define dh_reg 122
232#define bh_reg 123
233
234#define ax_reg 124
235#define cx_reg 125
236#define dx_reg 126
237#define bx_reg 127
238#define sp_reg 128
239#define bp_reg 129
240#define si_reg 130
241#define di_reg 131
242
243#define indir_dx_reg 150
244
245#define GRP1b NULL, NULL, 0
246#define GRP1S NULL, NULL, 1
247#define GRP1Ss NULL, NULL, 2
248#define GRP2b NULL, NULL, 3
249#define GRP2S NULL, NULL, 4
250#define GRP2b_one NULL, NULL, 5
251#define GRP2S_one NULL, NULL, 6
252#define GRP2b_cl NULL, NULL, 7
253#define GRP2S_cl NULL, NULL, 8
254#define GRP3b NULL, NULL, 9
255#define GRP3S NULL, NULL, 10
256#define GRP4 NULL, NULL, 11
257#define GRP5 NULL, NULL, 12
258#define GRP6 NULL, NULL, 13
259#define GRP7 NULL, NULL, 14
260#define GRP8 NULL, NULL, 15
726257a8 261#define GRP9 NULL, NULL, 16
eedca9da
ILT
262#define GRP10 NULL, NULL, 17
263#define GRP11 NULL, NULL, 18
264#define GRP12 NULL, NULL, 19
5d0734a7
JK
265
266#define FLOATCODE 50
267#define FLOAT NULL, NULL, FLOATCODE
268
269struct dis386 {
270 char *name;
41b96d55 271 op_rtn op1;
5d0734a7 272 int bytemode1;
41b96d55 273 op_rtn op2;
5d0734a7 274 int bytemode2;
41b96d55 275 op_rtn op3;
5d0734a7
JK
276 int bytemode3;
277};
278
5f90dab1
ILT
279/* Upper case letters in the instruction names here are macros.
280 'A' => print 'b' if no register operands or suffix_always is true
281 'B' => print 'b' if suffix_always is true
282 'E' => print 'e' if 32-bit form of jcxz
283 'L' => print 'l' if suffix_always is true
284 'N' => print 'n' if instruction has no wait "prefix"
285 'P' => print 'w' or 'l' if instruction has an operand size prefix,
286 or suffix_always is true
287 'Q' => print 'w' or 'l' if no register operands or suffix_always is true
288 'R' => print 'w' or 'l'
289 'S' => print 'w' or 'l' if suffix_always is true
290 'W' => print 'b' or 'w'
291*/
292
be0c8b05 293static struct dis386 dis386[] = {
5d0734a7 294 /* 00 */
5f90dab1 295 { "addB", Eb, Gb },
5d0734a7 296 { "addS", Ev, Gv },
5f90dab1 297 { "addB", Gb, Eb },
5d0734a7 298 { "addS", Gv, Ev },
5f90dab1 299 { "addB", AL, Ib },
5d0734a7 300 { "addS", eAX, Iv },
5f90dab1
ILT
301 { "pushP", es },
302 { "popP", es },
5d0734a7 303 /* 08 */
5f90dab1 304 { "orB", Eb, Gb },
5d0734a7 305 { "orS", Ev, Gv },
5f90dab1 306 { "orB", Gb, Eb },
5d0734a7 307 { "orS", Gv, Ev },
5f90dab1 308 { "orB", AL, Ib },
5d0734a7 309 { "orS", eAX, Iv },
5f90dab1 310 { "pushP", cs },
5d0734a7
JK
311 { "(bad)" }, /* 0x0f extended opcode escape */
312 /* 10 */
5f90dab1 313 { "adcB", Eb, Gb },
5d0734a7 314 { "adcS", Ev, Gv },
5f90dab1 315 { "adcB", Gb, Eb },
5d0734a7 316 { "adcS", Gv, Ev },
5f90dab1 317 { "adcB", AL, Ib },
5d0734a7 318 { "adcS", eAX, Iv },
5f90dab1
ILT
319 { "pushP", ss },
320 { "popP", ss },
5d0734a7 321 /* 18 */
5f90dab1 322 { "sbbB", Eb, Gb },
5d0734a7 323 { "sbbS", Ev, Gv },
5f90dab1 324 { "sbbB", Gb, Eb },
5d0734a7 325 { "sbbS", Gv, Ev },
5f90dab1 326 { "sbbB", AL, Ib },
5d0734a7 327 { "sbbS", eAX, Iv },
5f90dab1
ILT
328 { "pushP", ds },
329 { "popP", ds },
5d0734a7 330 /* 20 */
5f90dab1 331 { "andB", Eb, Gb },
5d0734a7 332 { "andS", Ev, Gv },
5f90dab1 333 { "andB", Gb, Eb },
5d0734a7 334 { "andS", Gv, Ev },
5f90dab1 335 { "andB", AL, Ib },
5d0734a7
JK
336 { "andS", eAX, Iv },
337 { "(bad)" }, /* SEG ES prefix */
338 { "daa" },
339 /* 28 */
5f90dab1 340 { "subB", Eb, Gb },
5d0734a7 341 { "subS", Ev, Gv },
5f90dab1 342 { "subB", Gb, Eb },
5d0734a7 343 { "subS", Gv, Ev },
5f90dab1 344 { "subB", AL, Ib },
5d0734a7
JK
345 { "subS", eAX, Iv },
346 { "(bad)" }, /* SEG CS prefix */
347 { "das" },
348 /* 30 */
5f90dab1 349 { "xorB", Eb, Gb },
5d0734a7 350 { "xorS", Ev, Gv },
5f90dab1 351 { "xorB", Gb, Eb },
5d0734a7 352 { "xorS", Gv, Ev },
5f90dab1 353 { "xorB", AL, Ib },
5d0734a7
JK
354 { "xorS", eAX, Iv },
355 { "(bad)" }, /* SEG SS prefix */
356 { "aaa" },
357 /* 38 */
5f90dab1 358 { "cmpB", Eb, Gb },
5d0734a7 359 { "cmpS", Ev, Gv },
5f90dab1 360 { "cmpB", Gb, Eb },
5d0734a7 361 { "cmpS", Gv, Ev },
5f90dab1 362 { "cmpB", AL, Ib },
5d0734a7
JK
363 { "cmpS", eAX, Iv },
364 { "(bad)" }, /* SEG DS prefix */
365 { "aas" },
366 /* 40 */
367 { "incS", eAX },
368 { "incS", eCX },
369 { "incS", eDX },
370 { "incS", eBX },
371 { "incS", eSP },
372 { "incS", eBP },
373 { "incS", eSI },
374 { "incS", eDI },
375 /* 48 */
376 { "decS", eAX },
377 { "decS", eCX },
378 { "decS", eDX },
379 { "decS", eBX },
380 { "decS", eSP },
381 { "decS", eBP },
382 { "decS", eSI },
383 { "decS", eDI },
384 /* 50 */
385 { "pushS", eAX },
386 { "pushS", eCX },
387 { "pushS", eDX },
388 { "pushS", eBX },
389 { "pushS", eSP },
390 { "pushS", eBP },
391 { "pushS", eSI },
392 { "pushS", eDI },
393 /* 58 */
394 { "popS", eAX },
395 { "popS", eCX },
396 { "popS", eDX },
397 { "popS", eBX },
398 { "popS", eSP },
399 { "popS", eBP },
400 { "popS", eSI },
401 { "popS", eDI },
402 /* 60 */
5f90dab1
ILT
403 { "pushaP" },
404 { "popaP" },
5d0734a7
JK
405 { "boundS", Gv, Ma },
406 { "arpl", Ew, Gw },
407 { "(bad)" }, /* seg fs */
408 { "(bad)" }, /* seg gs */
409 { "(bad)" }, /* op size prefix */
410 { "(bad)" }, /* adr size prefix */
411 /* 68 */
5f90dab1 412 { "pushP", Iv }, /* 386 book wrong */
5d0734a7 413 { "imulS", Gv, Ev, Iv },
5f90dab1
ILT
414 { "pushP", sIb }, /* push of byte really pushes 2 or 4 bytes */
415 { "imulS", Gv, Ev, sIb },
5d0734a7 416 { "insb", Yb, indirDX },
5f90dab1 417 { "insR", Yv, indirDX },
5d0734a7 418 { "outsb", indirDX, Xb },
5f90dab1 419 { "outsR", indirDX, Xv },
5d0734a7 420 /* 70 */
03db5a93 421 { "jo", Jb },
5d0734a7 422 { "jno", Jb },
03db5a93 423 { "jb", Jb },
5d0734a7 424 { "jae", Jb },
03db5a93 425 { "je", Jb },
5d0734a7
JK
426 { "jne", Jb },
427 { "jbe", Jb },
03db5a93 428 { "ja", Jb },
5d0734a7 429 /* 78 */
03db5a93 430 { "js", Jb },
5d0734a7 431 { "jns", Jb },
03db5a93 432 { "jp", Jb },
5d0734a7 433 { "jnp", Jb },
03db5a93 434 { "jl", Jb },
5f90dab1 435 { "jge", Jb },
5d0734a7 436 { "jle", Jb },
03db5a93 437 { "jg", Jb },
5d0734a7
JK
438 /* 80 */
439 { GRP1b },
440 { GRP1S },
441 { "(bad)" },
442 { GRP1Ss },
5f90dab1 443 { "testB", Eb, Gb },
5d0734a7 444 { "testS", Ev, Gv },
5f90dab1 445 { "xchgB", Eb, Gb },
5d0734a7
JK
446 { "xchgS", Ev, Gv },
447 /* 88 */
5f90dab1 448 { "movB", Eb, Gb },
5d0734a7 449 { "movS", Ev, Gv },
5f90dab1 450 { "movB", Gb, Eb },
5d0734a7 451 { "movS", Gv, Ev },
5f90dab1 452 { "movQ", Ev, Sw },
5d0734a7 453 { "leaS", Gv, M },
5f90dab1
ILT
454 { "movQ", Sw, Ev },
455 { "popQ", Ev },
5d0734a7
JK
456 /* 90 */
457 { "nop" },
458 { "xchgS", eCX, eAX },
459 { "xchgS", eDX, eAX },
460 { "xchgS", eBX, eAX },
461 { "xchgS", eSP, eAX },
462 { "xchgS", eBP, eAX },
463 { "xchgS", eSI, eAX },
464 { "xchgS", eDI, eAX },
465 /* 98 */
5f90dab1
ILT
466 { "cWtR" },
467 { "cRtd" },
468 { "lcallP", Ap },
5d0734a7 469 { "(bad)" }, /* fwait */
5f90dab1
ILT
470 { "pushfP" },
471 { "popfP" },
5d0734a7
JK
472 { "sahf" },
473 { "lahf" },
474 /* a0 */
5f90dab1 475 { "movB", AL, Ob },
5d0734a7 476 { "movS", eAX, Ov },
5f90dab1 477 { "movB", Ob, AL },
5d0734a7
JK
478 { "movS", Ov, eAX },
479 { "movsb", Yb, Xb },
5f90dab1
ILT
480 { "movsR", Yv, Xv },
481 { "cmpsb", Xb, Yb },
482 { "cmpsR", Xv, Yv },
5d0734a7 483 /* a8 */
5f90dab1 484 { "testB", AL, Ib },
5d0734a7 485 { "testS", eAX, Iv },
5f90dab1 486 { "stosB", Yb, AL },
5d0734a7 487 { "stosS", Yv, eAX },
5f90dab1 488 { "lodsB", AL, Xb },
5d0734a7 489 { "lodsS", eAX, Xv },
5f90dab1 490 { "scasB", AL, Yb },
a279b1f5 491 { "scasS", eAX, Yv },
5d0734a7 492 /* b0 */
5f90dab1
ILT
493 { "movB", AL, Ib },
494 { "movB", CL, Ib },
495 { "movB", DL, Ib },
496 { "movB", BL, Ib },
497 { "movB", AH, Ib },
498 { "movB", CH, Ib },
499 { "movB", DH, Ib },
500 { "movB", BH, Ib },
5d0734a7
JK
501 /* b8 */
502 { "movS", eAX, Iv },
503 { "movS", eCX, Iv },
504 { "movS", eDX, Iv },
505 { "movS", eBX, Iv },
506 { "movS", eSP, Iv },
507 { "movS", eBP, Iv },
508 { "movS", eSI, Iv },
509 { "movS", eDI, Iv },
510 /* c0 */
511 { GRP2b },
512 { GRP2S },
5f90dab1
ILT
513 { "retP", Iw },
514 { "retP" },
5d0734a7
JK
515 { "lesS", Gv, Mp },
516 { "ldsS", Gv, Mp },
5f90dab1
ILT
517 { "movA", Eb, Ib },
518 { "movQ", Ev, Iv },
5d0734a7 519 /* c8 */
5f90dab1
ILT
520 { "enterP", Iw, Ib },
521 { "leaveP" },
522 { "lretP", Iw },
523 { "lretP" },
5d0734a7
JK
524 { "int3" },
525 { "int", Ib },
526 { "into" },
5f90dab1 527 { "iretP" },
5d0734a7
JK
528 /* d0 */
529 { GRP2b_one },
530 { GRP2S_one },
531 { GRP2b_cl },
532 { GRP2S_cl },
5f90dab1
ILT
533 { "aam", sIb },
534 { "aad", sIb },
5d0734a7 535 { "(bad)" },
80119c9e 536 { "xlat", DSBX },
5d0734a7
JK
537 /* d8 */
538 { FLOAT },
539 { FLOAT },
540 { FLOAT },
541 { FLOAT },
542 { FLOAT },
543 { FLOAT },
544 { FLOAT },
545 { FLOAT },
546 /* e0 */
547 { "loopne", Jb },
548 { "loope", Jb },
549 { "loop", Jb },
5f90dab1
ILT
550 { "jEcxz", Jb },
551 { "inB", AL, Ib },
5d0734a7 552 { "inS", eAX, Ib },
5f90dab1 553 { "outB", Ib, AL },
5d0734a7
JK
554 { "outS", Ib, eAX },
555 /* e8 */
5f90dab1
ILT
556 { "callP", Av },
557 { "jmpP", Jv },
558 { "ljmpP", Ap },
5d0734a7 559 { "jmp", Jb },
5f90dab1 560 { "inB", AL, indirDX },
5d0734a7 561 { "inS", eAX, indirDX },
5f90dab1 562 { "outB", indirDX, AL },
5d0734a7
JK
563 { "outS", indirDX, eAX },
564 /* f0 */
565 { "(bad)" }, /* lock prefix */
566 { "(bad)" },
567 { "(bad)" }, /* repne */
568 { "(bad)" }, /* repz */
569 { "hlt" },
570 { "cmc" },
571 { GRP3b },
572 { GRP3S },
573 /* f8 */
574 { "clc" },
575 { "stc" },
576 { "cli" },
577 { "sti" },
578 { "cld" },
579 { "std" },
580 { GRP4 },
581 { GRP5 },
582};
583
be0c8b05 584static struct dis386 dis386_twobyte[] = {
5d0734a7
JK
585 /* 00 */
586 { GRP6 },
587 { GRP7 },
588 { "larS", Gv, Ew },
589 { "lslS", Gv, Ew },
590 { "(bad)" },
591 { "(bad)" },
592 { "clts" },
593 { "(bad)" },
594 /* 08 */
595 { "invd" },
596 { "wbinvd" },
5f90dab1
ILT
597 { "(bad)" },
598 { "ud2a" },
5d0734a7
JK
599 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
600 /* 10 */
601 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
602 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
603 /* 18 */
604 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
605 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
606 /* 20 */
607 /* these are all backward in appendix A of the intel book */
5f90dab1
ILT
608 { "movL", Rd, Cd },
609 { "movL", Rd, Dd },
610 { "movL", Cd, Rd },
611 { "movL", Dd, Rd },
612 { "movL", Rd, Td },
5d0734a7 613 { "(bad)" },
5f90dab1 614 { "movL", Td, Rd },
5d0734a7
JK
615 { "(bad)" },
616 /* 28 */
617 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
618 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
619 /* 30 */
1d935cf6 620 { "wrmsr" }, { "rdtsc" }, { "rdmsr" }, { "rdpmc" },
5d0734a7
JK
621 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
622 /* 38 */
623 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
624 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
625 /* 40 */
1d935cf6
MM
626 { "cmovo", Gv,Ev }, { "cmovno", Gv,Ev }, { "cmovb", Gv,Ev }, { "cmovae", Gv,Ev },
627 { "cmove", Gv,Ev }, { "cmovne", Gv,Ev }, { "cmovbe", Gv,Ev }, { "cmova", Gv,Ev },
5d0734a7 628 /* 48 */
1d935cf6
MM
629 { "cmovs", Gv,Ev }, { "cmovns", Gv,Ev }, { "cmovp", Gv,Ev }, { "cmovnp", Gv,Ev },
630 { "cmovl", Gv,Ev }, { "cmovge", Gv,Ev }, { "cmovle", Gv,Ev }, { "cmovg", Gv,Ev },
5d0734a7
JK
631 /* 50 */
632 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
633 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
634 /* 58 */
635 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
636 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
637 /* 60 */
eedca9da
ILT
638 { "punpcklbw", MX, EM },
639 { "punpcklwd", MX, EM },
640 { "punpckldq", MX, EM },
641 { "packsswb", MX, EM },
642 { "pcmpgtb", MX, EM },
643 { "pcmpgtw", MX, EM },
644 { "pcmpgtd", MX, EM },
645 { "packuswb", MX, EM },
5d0734a7 646 /* 68 */
eedca9da
ILT
647 { "punpckhbw", MX, EM },
648 { "punpckhwd", MX, EM },
649 { "punpckhdq", MX, EM },
650 { "packssdw", MX, EM },
651 { "(bad)" }, { "(bad)" },
652 { "movd", MX, Ev },
653 { "movq", MX, EM },
5d0734a7 654 /* 70 */
eedca9da
ILT
655 { "(bad)" },
656 { GRP10 },
657 { GRP11 },
658 { GRP12 },
659 { "pcmpeqb", MX, EM },
660 { "pcmpeqw", MX, EM },
661 { "pcmpeqd", MX, EM },
662 { "emms" },
5d0734a7
JK
663 /* 78 */
664 { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
eedca9da
ILT
665 { "(bad)" }, { "(bad)" },
666 { "movd", Ev, MX },
667 { "movq", EM, MX },
5d0734a7
JK
668 /* 80 */
669 { "jo", Jv },
670 { "jno", Jv },
671 { "jb", Jv },
672 { "jae", Jv },
673 { "je", Jv },
674 { "jne", Jv },
675 { "jbe", Jv },
676 { "ja", Jv },
677 /* 88 */
678 { "js", Jv },
679 { "jns", Jv },
680 { "jp", Jv },
681 { "jnp", Jv },
682 { "jl", Jv },
683 { "jge", Jv },
684 { "jle", Jv },
685 { "jg", Jv },
686 /* 90 */
687 { "seto", Eb },
688 { "setno", Eb },
689 { "setb", Eb },
690 { "setae", Eb },
691 { "sete", Eb },
692 { "setne", Eb },
693 { "setbe", Eb },
694 { "seta", Eb },
695 /* 98 */
696 { "sets", Eb },
697 { "setns", Eb },
698 { "setp", Eb },
699 { "setnp", Eb },
700 { "setl", Eb },
701 { "setge", Eb },
702 { "setle", Eb },
703 { "setg", Eb },
704 /* a0 */
5f90dab1
ILT
705 { "pushP", fs },
706 { "popP", fs },
726257a8 707 { "cpuid" },
5d0734a7
JK
708 { "btS", Ev, Gv },
709 { "shldS", Ev, Gv, Ib },
710 { "shldS", Ev, Gv, CL },
711 { "(bad)" },
712 { "(bad)" },
713 /* a8 */
5f90dab1
ILT
714 { "pushP", gs },
715 { "popP", gs },
726257a8 716 { "rsm" },
5d0734a7
JK
717 { "btsS", Ev, Gv },
718 { "shrdS", Ev, Gv, Ib },
719 { "shrdS", Ev, Gv, CL },
720 { "(bad)" },
721 { "imulS", Gv, Ev },
722 /* b0 */
5f90dab1 723 { "cmpxchgB", Eb, Gb },
5d0734a7
JK
724 { "cmpxchgS", Ev, Gv },
725 { "lssS", Gv, Mp }, /* 386 lists only Mp */
726 { "btrS", Ev, Gv },
727 { "lfsS", Gv, Mp }, /* 386 lists only Mp */
728 { "lgsS", Gv, Mp }, /* 386 lists only Mp */
5f90dab1
ILT
729 { "movzbR", Gv, Eb },
730 { "movzwR", Gv, Ew }, /* yes, there really is movzww ! */
5d0734a7 731 /* b8 */
5d0734a7 732 { "(bad)" },
5f90dab1 733 { "ud2b" },
5d0734a7
JK
734 { GRP8 },
735 { "btcS", Ev, Gv },
736 { "bsfS", Gv, Ev },
737 { "bsrS", Gv, Ev },
5f90dab1
ILT
738 { "movsbR", Gv, Eb },
739 { "movswR", Gv, Ew }, /* yes, there really is movsww ! */
5d0734a7 740 /* c0 */
5f90dab1 741 { "xaddB", Eb, Gb },
5d0734a7 742 { "xaddS", Ev, Gv },
726257a8
KR
743 { "(bad)" },
744 { "(bad)" },
745 { "(bad)" },
746 { "(bad)" },
747 { "(bad)" },
748 { GRP9 },
5d0734a7 749 /* c8 */
5f90dab1 750 { "bswap", eAX }, /* bswap doesn't support 16 bit regs */
5d0734a7
JK
751 { "bswap", eCX },
752 { "bswap", eDX },
753 { "bswap", eBX },
754 { "bswap", eSP },
755 { "bswap", eBP },
756 { "bswap", eSI },
757 { "bswap", eDI },
758 /* d0 */
eedca9da
ILT
759 { "(bad)" },
760 { "psrlw", MX, EM },
761 { "psrld", MX, EM },
762 { "psrlq", MX, EM },
763 { "(bad)" },
764 { "pmullw", MX, EM },
765 { "(bad)" }, { "(bad)" },
5d0734a7 766 /* d8 */
eedca9da
ILT
767 { "psubusb", MX, EM },
768 { "psubusw", MX, EM },
769 { "(bad)" },
770 { "pand", MX, EM },
771 { "paddusb", MX, EM },
772 { "paddusw", MX, EM },
773 { "(bad)" },
774 { "pandn", MX, EM },
5d0734a7 775 /* e0 */
eedca9da
ILT
776 { "(bad)" },
777 { "psraw", MX, EM },
778 { "psrad", MX, EM },
779 { "(bad)" },
780 { "(bad)" },
781 { "pmulhw", MX, EM },
782 { "(bad)" }, { "(bad)" },
5d0734a7 783 /* e8 */
eedca9da
ILT
784 { "psubsb", MX, EM },
785 { "psubsw", MX, EM },
786 { "(bad)" },
787 { "por", MX, EM },
788 { "paddsb", MX, EM },
789 { "paddsw", MX, EM },
790 { "(bad)" },
791 { "pxor", MX, EM },
5d0734a7 792 /* f0 */
eedca9da
ILT
793 { "(bad)" },
794 { "psllw", MX, EM },
795 { "pslld", MX, EM },
796 { "psllq", MX, EM },
797 { "(bad)" },
798 { "pmaddwd", MX, EM },
799 { "(bad)" }, { "(bad)" },
5d0734a7 800 /* f8 */
eedca9da
ILT
801 { "psubb", MX, EM },
802 { "psubw", MX, EM },
803 { "psubd", MX, EM },
804 { "(bad)" },
805 { "paddb", MX, EM },
806 { "paddw", MX, EM },
807 { "paddd", MX, EM },
808 { "(bad)" }
5d0734a7
JK
809};
810
03db5a93
ILT
811static const unsigned char onebyte_has_modrm[256] = {
812 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
813 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
814 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
815 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
816 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
817 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
818 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
819 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
820 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
821 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
822 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
823 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
824 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
825 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
826 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
827 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1
828};
829
830static const unsigned char twobyte_has_modrm[256] = {
eedca9da
ILT
831 /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
832 /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
833 /* 20 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 2f */
834 /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
835 /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
836 /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
837 /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1, /* 6f */
838 /* 70 */ 0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
839 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
840 /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
841 /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
842 /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
843 /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
409595b8 844 /* d0 */ 0,1,1,1,0,1,0,0,1,1,0,1,1,1,0,1, /* df */
eedca9da
ILT
845 /* e0 */ 0,1,1,0,0,1,0,0,1,1,0,1,1,1,0,1, /* ef */
846 /* f0 */ 0,1,1,1,0,1,0,0,1,1,1,0,1,1,1,0 /* ff */
03db5a93
ILT
847};
848
5d0734a7
JK
849static char obuf[100];
850static char *obufp;
851static char scratchbuf[100];
852static unsigned char *start_codep;
853static unsigned char *codep;
854static disassemble_info *the_info;
855static int mod;
856static int rm;
857static int reg;
be0c8b05 858static void oappend PARAMS ((char *s));
5d0734a7
JK
859
860static char *names32[]={
861 "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
862};
863static char *names16[] = {
864 "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
865};
866static char *names8[] = {
867 "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
868};
869static char *names_seg[] = {
870 "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
871};
be0c8b05
SG
872static char *index16[] = {
873 "bx+si","bx+di","bp+si","bp+di","si","di","bp","bx"
874};
5d0734a7 875
be0c8b05 876static struct dis386 grps[][8] = {
5d0734a7
JK
877 /* GRP1b */
878 {
5f90dab1
ILT
879 { "addA", Eb, Ib },
880 { "orA", Eb, Ib },
881 { "adcA", Eb, Ib },
882 { "sbbA", Eb, Ib },
883 { "andA", Eb, Ib },
884 { "subA", Eb, Ib },
885 { "xorA", Eb, Ib },
886 { "cmpA", Eb, Ib }
5d0734a7
JK
887 },
888 /* GRP1S */
889 {
5f90dab1
ILT
890 { "addQ", Ev, Iv },
891 { "orQ", Ev, Iv },
892 { "adcQ", Ev, Iv },
893 { "sbbQ", Ev, Iv },
894 { "andQ", Ev, Iv },
895 { "subQ", Ev, Iv },
896 { "xorQ", Ev, Iv },
897 { "cmpQ", Ev, Iv }
5d0734a7
JK
898 },
899 /* GRP1Ss */
900 {
5f90dab1
ILT
901 { "addQ", Ev, sIb },
902 { "orQ", Ev, sIb },
903 { "adcQ", Ev, sIb },
904 { "sbbQ", Ev, sIb },
905 { "andQ", Ev, sIb },
906 { "subQ", Ev, sIb },
907 { "xorQ", Ev, sIb },
908 { "cmpQ", Ev, sIb }
5d0734a7
JK
909 },
910 /* GRP2b */
911 {
5f90dab1
ILT
912 { "rolA", Eb, Ib },
913 { "rorA", Eb, Ib },
914 { "rclA", Eb, Ib },
915 { "rcrA", Eb, Ib },
916 { "shlA", Eb, Ib },
917 { "shrA", Eb, Ib },
5d0734a7 918 { "(bad)" },
5f90dab1 919 { "sarA", Eb, Ib },
5d0734a7
JK
920 },
921 /* GRP2S */
922 {
5f90dab1
ILT
923 { "rolQ", Ev, Ib },
924 { "rorQ", Ev, Ib },
925 { "rclQ", Ev, Ib },
926 { "rcrQ", Ev, Ib },
927 { "shlQ", Ev, Ib },
928 { "shrQ", Ev, Ib },
5d0734a7 929 { "(bad)" },
5f90dab1 930 { "sarQ", Ev, Ib },
5d0734a7
JK
931 },
932 /* GRP2b_one */
933 {
5f90dab1
ILT
934 { "rolA", Eb },
935 { "rorA", Eb },
936 { "rclA", Eb },
937 { "rcrA", Eb },
938 { "shlA", Eb },
939 { "shrA", Eb },
5d0734a7 940 { "(bad)" },
5f90dab1 941 { "sarA", Eb },
5d0734a7
JK
942 },
943 /* GRP2S_one */
944 {
5f90dab1
ILT
945 { "rolQ", Ev },
946 { "rorQ", Ev },
947 { "rclQ", Ev },
948 { "rcrQ", Ev },
949 { "shlQ", Ev },
950 { "shrQ", Ev },
5d0734a7 951 { "(bad)" },
5f90dab1 952 { "sarQ", Ev },
5d0734a7
JK
953 },
954 /* GRP2b_cl */
955 {
5f90dab1
ILT
956 { "rolA", Eb, CL },
957 { "rorA", Eb, CL },
958 { "rclA", Eb, CL },
959 { "rcrA", Eb, CL },
960 { "shlA", Eb, CL },
961 { "shrA", Eb, CL },
5d0734a7 962 { "(bad)" },
5f90dab1 963 { "sarA", Eb, CL },
5d0734a7
JK
964 },
965 /* GRP2S_cl */
966 {
5f90dab1
ILT
967 { "rolQ", Ev, CL },
968 { "rorQ", Ev, CL },
969 { "rclQ", Ev, CL },
970 { "rcrQ", Ev, CL },
971 { "shlQ", Ev, CL },
972 { "shrQ", Ev, CL },
5d0734a7 973 { "(bad)" },
5f90dab1 974 { "sarQ", Ev, CL }
5d0734a7
JK
975 },
976 /* GRP3b */
977 {
5f90dab1 978 { "testA", Eb, Ib },
5d0734a7 979 { "(bad)", Eb },
5f90dab1
ILT
980 { "notA", Eb },
981 { "negA", Eb },
982 { "mulB", AL, Eb },
983 { "imulB", AL, Eb },
984 { "divB", AL, Eb },
985 { "idivB", AL, Eb }
5d0734a7
JK
986 },
987 /* GRP3S */
988 {
5f90dab1 989 { "testQ", Ev, Iv },
5d0734a7 990 { "(bad)" },
5f90dab1
ILT
991 { "notQ", Ev },
992 { "negQ", Ev },
5d0734a7
JK
993 { "mulS", eAX, Ev },
994 { "imulS", eAX, Ev },
995 { "divS", eAX, Ev },
996 { "idivS", eAX, Ev },
997 },
998 /* GRP4 */
999 {
5f90dab1
ILT
1000 { "incA", Eb },
1001 { "decA", Eb },
5d0734a7
JK
1002 { "(bad)" },
1003 { "(bad)" },
1004 { "(bad)" },
1005 { "(bad)" },
1006 { "(bad)" },
1007 { "(bad)" },
1008 },
1009 /* GRP5 */
1010 {
5f90dab1
ILT
1011 { "incQ", Ev },
1012 { "decQ", Ev },
1013 { "callP", indirEv },
1014 { "lcallP", indirEv },
1015 { "jmpP", indirEv },
1016 { "ljmpP", indirEv },
1017 { "pushQ", Ev },
5d0734a7
JK
1018 { "(bad)" },
1019 },
1020 /* GRP6 */
1021 {
1022 { "sldt", Ew },
1023 { "str", Ew },
1024 { "lldt", Ew },
1025 { "ltr", Ew },
1026 { "verr", Ew },
1027 { "verw", Ew },
1028 { "(bad)" },
1029 { "(bad)" }
1030 },
1031 /* GRP7 */
1032 {
1033 { "sgdt", Ew },
1034 { "sidt", Ew },
1035 { "lgdt", Ew },
1036 { "lidt", Ew },
1037 { "smsw", Ew },
1038 { "(bad)" },
1039 { "lmsw", Ew },
1040 { "invlpg", Ew },
1041 },
1042 /* GRP8 */
1043 {
1044 { "(bad)" },
1045 { "(bad)" },
1046 { "(bad)" },
1047 { "(bad)" },
5f90dab1
ILT
1048 { "btQ", Ev, Ib },
1049 { "btsQ", Ev, Ib },
1050 { "btrQ", Ev, Ib },
1051 { "btcQ", Ev, Ib },
726257a8
KR
1052 },
1053 /* GRP9 */
1054 {
1055 { "(bad)" },
1d935cf6 1056 { "cmpxchg8b", Ev },
726257a8
KR
1057 { "(bad)" },
1058 { "(bad)" },
1059 { "(bad)" },
1060 { "(bad)" },
1061 { "(bad)" },
1062 { "(bad)" },
eedca9da
ILT
1063 },
1064 /* GRP10 */
1065 {
1066 { "(bad)" },
1067 { "(bad)" },
1068 { "psrlw", MS, Ib },
1069 { "(bad)" },
1070 { "psraw", MS, Ib },
1071 { "(bad)" },
1072 { "psllw", MS, Ib },
1073 { "(bad)" },
1074 },
1075 /* GRP11 */
1076 {
1077 { "(bad)" },
1078 { "(bad)" },
1079 { "psrld", MS, Ib },
1080 { "(bad)" },
1081 { "psrad", MS, Ib },
1082 { "(bad)" },
1083 { "pslld", MS, Ib },
1084 { "(bad)" },
1085 },
1086 /* GRP12 */
1087 {
1088 { "(bad)" },
1089 { "(bad)" },
1090 { "psrlq", MS, Ib },
1091 { "(bad)" },
1092 { "(bad)" },
1093 { "(bad)" },
1094 { "psllq", MS, Ib },
1095 { "(bad)" },
5d0734a7
JK
1096 }
1097};
1098
1099#define PREFIX_REPZ 1
1100#define PREFIX_REPNZ 2
1101#define PREFIX_LOCK 4
1102#define PREFIX_CS 8
1103#define PREFIX_SS 0x10
1104#define PREFIX_DS 0x20
1105#define PREFIX_ES 0x40
1106#define PREFIX_FS 0x80
1107#define PREFIX_GS 0x100
1108#define PREFIX_DATA 0x200
80119c9e 1109#define PREFIX_ADDR 0x400
5d0734a7
JK
1110#define PREFIX_FWAIT 0x800
1111
1112static int prefixes;
1113
1114static void
1115ckprefix ()
1116{
1117 prefixes = 0;
1118 while (1)
1119 {
1120 FETCH_DATA (the_info, codep + 1);
1121 switch (*codep)
1122 {
1123 case 0xf3:
1124 prefixes |= PREFIX_REPZ;
1125 break;
1126 case 0xf2:
1127 prefixes |= PREFIX_REPNZ;
1128 break;
1129 case 0xf0:
1130 prefixes |= PREFIX_LOCK;
1131 break;
1132 case 0x2e:
1133 prefixes |= PREFIX_CS;
1134 break;
1135 case 0x36:
1136 prefixes |= PREFIX_SS;
1137 break;
1138 case 0x3e:
1139 prefixes |= PREFIX_DS;
1140 break;
1141 case 0x26:
1142 prefixes |= PREFIX_ES;
1143 break;
1144 case 0x64:
1145 prefixes |= PREFIX_FS;
1146 break;
1147 case 0x65:
1148 prefixes |= PREFIX_GS;
1149 break;
1150 case 0x66:
1151 prefixes |= PREFIX_DATA;
1152 break;
1153 case 0x67:
80119c9e 1154 prefixes |= PREFIX_ADDR;
5d0734a7
JK
1155 break;
1156 case 0x9b:
1157 prefixes |= PREFIX_FWAIT;
5f90dab1
ILT
1158 codep++; /* fwait is really an instruction */
1159 return; /* so stop accumulating prefixes */
5d0734a7
JK
1160 default:
1161 return;
1162 }
1163 codep++;
1164 }
1165}
1166
5d0734a7 1167static char op1out[100], op2out[100], op3out[100];
80ade993
ILT
1168static int op_ad, op_index[3];
1169static unsigned int op_address[3];
1170static unsigned int start_pc;
5d0734a7
JK
1171
1172\f
1173/*
1174 * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
1175 * (see topic "Redundant prefixes" in the "Differences from 8086"
1176 * section of the "Virtual 8086 Mode" chapter.)
1177 * 'pc' should be the address of this instruction, it will
1178 * be used to print the target address if this is a relative jump or call
1179 * The function returns the length of this instruction in bytes.
1180 */
1181
80119c9e 1182int print_insn_x86 PARAMS ((bfd_vma pc, disassemble_info *info, int sizeflag));
5f90dab1 1183
5d0734a7
JK
1184int
1185print_insn_i386 (pc, info)
1186 bfd_vma pc;
1187 disassemble_info *info;
be0c8b05 1188{
5f90dab1 1189 int flags;
d9ad578c 1190 if (info->mach == bfd_mach_i386_i386)
5f90dab1 1191 flags = AFLAG|DFLAG;
d9ad578c 1192 else if (info->mach == bfd_mach_i386_i8086)
5f90dab1 1193 flags = 0;
d9ad578c
SG
1194 else
1195 abort ();
5f90dab1 1196 return print_insn_x86 (pc, info, flags);
be0c8b05
SG
1197}
1198
1199int
80119c9e 1200print_insn_x86 (pc, info, sizeflag)
be0c8b05
SG
1201 bfd_vma pc;
1202 disassemble_info *info;
80119c9e 1203 int sizeflag;
5d0734a7
JK
1204{
1205 struct dis386 *dp;
1206 int i;
5f90dab1 1207 int two_source_ops;
5d0734a7
JK
1208 char *first, *second, *third;
1209 int needcomma;
03db5a93
ILT
1210 unsigned char need_modrm;
1211
726257a8 1212 struct dis_private priv;
5d0734a7
JK
1213 bfd_byte *inbuf = priv.the_buffer;
1214
41b96d55
ILT
1215 /* The output looks better if we put 5 bytes on a line, since that
1216 puts long word instructions on a single line. */
1217 info->bytes_per_line = 5;
1218
5d0734a7
JK
1219 info->private_data = (PTR) &priv;
1220 priv.max_fetched = priv.the_buffer;
1221 priv.insn_start = pc;
1222 if (setjmp (priv.bailout) != 0)
1223 /* Error return. */
1224 return -1;
1225
1226 obuf[0] = 0;
1227 op1out[0] = 0;
1228 op2out[0] = 0;
1229 op3out[0] = 0;
1230
1231 op_index[0] = op_index[1] = op_index[2] = -1;
1232
1233 the_info = info;
1234 start_pc = pc;
1235 start_codep = inbuf;
1236 codep = inbuf;
1237
1238 ckprefix ();
1239
1240 FETCH_DATA (info, codep + 1);
5f90dab1 1241 two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
5d0734a7
JK
1242
1243 obufp = obuf;
1244
5f90dab1
ILT
1245 if ((prefixes & PREFIX_FWAIT)
1246 && ((*codep < 0xd8) || (*codep > 0xdf)))
1247 {
1248 /* fwait not followed by floating point instruction. */
1249 (*info->fprintf_func) (info->stream, "fwait");
1250 /* There may be other prefixes. Skip any before the fwait. */
1251 return codep - inbuf;
1252 }
1253
5d0734a7
JK
1254 if (prefixes & PREFIX_REPZ)
1255 oappend ("repz ");
1256 if (prefixes & PREFIX_REPNZ)
1257 oappend ("repnz ");
1258 if (prefixes & PREFIX_LOCK)
1259 oappend ("lock ");
1260
5d0734a7 1261 if (prefixes & PREFIX_DATA)
80119c9e 1262 sizeflag ^= DFLAG;
5d0734a7 1263
80119c9e 1264 if (prefixes & PREFIX_ADDR)
5d0734a7 1265 {
80119c9e
ILT
1266 sizeflag ^= AFLAG;
1267 if (sizeflag & AFLAG)
eedca9da
ILT
1268 oappend ("addr32 ");
1269 else
1270 oappend ("addr16 ");
5d0734a7
JK
1271 }
1272
1273 if (*codep == 0x0f)
1274 {
1275 FETCH_DATA (info, codep + 2);
1276 dp = &dis386_twobyte[*++codep];
03db5a93 1277 need_modrm = twobyte_has_modrm[*codep];
5d0734a7
JK
1278 }
1279 else
03db5a93
ILT
1280 {
1281 dp = &dis386[*codep];
1282 need_modrm = onebyte_has_modrm[*codep];
1283 }
5d0734a7 1284 codep++;
5c9b5f58 1285
03db5a93
ILT
1286 if (need_modrm)
1287 {
1288 FETCH_DATA (info, codep + 1);
1289 mod = (*codep >> 6) & 3;
1290 reg = (*codep >> 3) & 7;
1291 rm = *codep & 7;
1292 }
5c9b5f58 1293
5d0734a7
JK
1294 if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
1295 {
80119c9e 1296 dofloat (sizeflag);
5d0734a7
JK
1297 }
1298 else
1299 {
1300 if (dp->name == NULL)
1301 dp = &grps[dp->bytemode1][reg];
1302
80119c9e 1303 putop (dp->name, sizeflag);
5d0734a7
JK
1304
1305 obufp = op1out;
1306 op_ad = 2;
1307 if (dp->op1)
80119c9e 1308 (*dp->op1)(dp->bytemode1, sizeflag);
5d0734a7
JK
1309
1310 obufp = op2out;
1311 op_ad = 1;
1312 if (dp->op2)
80119c9e 1313 (*dp->op2)(dp->bytemode2, sizeflag);
5d0734a7
JK
1314
1315 obufp = op3out;
1316 op_ad = 0;
1317 if (dp->op3)
80119c9e 1318 (*dp->op3)(dp->bytemode3, sizeflag);
5d0734a7
JK
1319 }
1320
1321 obufp = obuf + strlen (obuf);
1322 for (i = strlen (obuf); i < 6; i++)
1323 oappend (" ");
1324 oappend (" ");
1325 (*info->fprintf_func) (info->stream, "%s", obuf);
1326
5f90dab1
ILT
1327 /* The enter and bound instructions are printed with operands in the same
1328 order as the intel book; everything else is printed in reverse order. */
1329 if (two_source_ops)
5d0734a7
JK
1330 {
1331 first = op1out;
1332 second = op2out;
1333 third = op3out;
1334 op_ad = op_index[0];
1335 op_index[0] = op_index[2];
1336 op_index[2] = op_ad;
1337 }
1338 else
1339 {
1340 first = op3out;
1341 second = op2out;
1342 third = op1out;
1343 }
1344 needcomma = 0;
1345 if (*first)
1346 {
1347 if (op_index[0] != -1)
80ade993 1348 (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
5d0734a7
JK
1349 else
1350 (*info->fprintf_func) (info->stream, "%s", first);
1351 needcomma = 1;
1352 }
1353 if (*second)
1354 {
1355 if (needcomma)
1356 (*info->fprintf_func) (info->stream, ",");
1357 if (op_index[1] != -1)
80ade993 1358 (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
5d0734a7
JK
1359 else
1360 (*info->fprintf_func) (info->stream, "%s", second);
1361 needcomma = 1;
1362 }
1363 if (*third)
1364 {
1365 if (needcomma)
1366 (*info->fprintf_func) (info->stream, ",");
1367 if (op_index[2] != -1)
80ade993 1368 (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
5d0734a7
JK
1369 else
1370 (*info->fprintf_func) (info->stream, "%s", third);
1371 }
80119c9e 1372 return codep - inbuf;
5d0734a7
JK
1373}
1374
be0c8b05 1375static char *float_mem[] = {
5d0734a7
JK
1376 /* d8 */
1377 "fadds",
1378 "fmuls",
1379 "fcoms",
1380 "fcomps",
1381 "fsubs",
1382 "fsubrs",
1383 "fdivs",
1384 "fdivrs",
1385 /* d9 */
1386 "flds",
1387 "(bad)",
1388 "fsts",
1389 "fstps",
1390 "fldenv",
1391 "fldcw",
1392 "fNstenv",
1393 "fNstcw",
1394 /* da */
1395 "fiaddl",
1396 "fimull",
1397 "ficoml",
1398 "ficompl",
1399 "fisubl",
1400 "fisubrl",
1401 "fidivl",
1402 "fidivrl",
1403 /* db */
1404 "fildl",
1405 "(bad)",
1406 "fistl",
1407 "fistpl",
1408 "(bad)",
1409 "fldt",
1410 "(bad)",
1411 "fstpt",
1412 /* dc */
1413 "faddl",
1414 "fmull",
1415 "fcoml",
1416 "fcompl",
1417 "fsubl",
1418 "fsubrl",
1419 "fdivl",
1420 "fdivrl",
1421 /* dd */
1422 "fldl",
1423 "(bad)",
1424 "fstl",
1425 "fstpl",
1426 "frstor",
1427 "(bad)",
1428 "fNsave",
1429 "fNstsw",
1430 /* de */
1431 "fiadd",
1432 "fimul",
1433 "ficom",
1434 "ficomp",
1435 "fisub",
1436 "fisubr",
1437 "fidiv",
1438 "fidivr",
1439 /* df */
1440 "fild",
1441 "(bad)",
1442 "fist",
1443 "fistp",
1444 "fbld",
1445 "fildll",
1446 "fbstp",
1447 "fistpll",
1448};
1449
1450#define ST OP_ST, 0
1451#define STi OP_STi, 0
5d0734a7
JK
1452
1453#define FGRPd9_2 NULL, NULL, 0
1454#define FGRPd9_4 NULL, NULL, 1
1455#define FGRPd9_5 NULL, NULL, 2
1456#define FGRPd9_6 NULL, NULL, 3
1457#define FGRPd9_7 NULL, NULL, 4
1458#define FGRPda_5 NULL, NULL, 5
1459#define FGRPdb_4 NULL, NULL, 6
1460#define FGRPde_3 NULL, NULL, 7
1461#define FGRPdf_4 NULL, NULL, 8
1462
be0c8b05 1463static struct dis386 float_reg[][8] = {
5d0734a7
JK
1464 /* d8 */
1465 {
1466 { "fadd", ST, STi },
1467 { "fmul", ST, STi },
1468 { "fcom", STi },
1469 { "fcomp", STi },
1470 { "fsub", ST, STi },
1471 { "fsubr", ST, STi },
1472 { "fdiv", ST, STi },
1473 { "fdivr", ST, STi },
1474 },
1475 /* d9 */
1476 {
1477 { "fld", STi },
1478 { "fxch", STi },
1479 { FGRPd9_2 },
1480 { "(bad)" },
1481 { FGRPd9_4 },
1482 { FGRPd9_5 },
1483 { FGRPd9_6 },
1484 { FGRPd9_7 },
1485 },
1486 /* da */
1487 {
1d935cf6
MM
1488 { "fcmovb", ST, STi },
1489 { "fcmove", ST, STi },
1490 { "fcmovbe",ST, STi },
1491 { "fcmovu", ST, STi },
5d0734a7
JK
1492 { "(bad)" },
1493 { FGRPda_5 },
1494 { "(bad)" },
1495 { "(bad)" },
1496 },
1497 /* db */
1498 {
1d935cf6
MM
1499 { "fcmovnb",ST, STi },
1500 { "fcmovne",ST, STi },
1501 { "fcmovnbe",ST, STi },
1502 { "fcmovnu",ST, STi },
5d0734a7 1503 { FGRPdb_4 },
1d935cf6
MM
1504 { "fucomi", ST, STi },
1505 { "fcomi", ST, STi },
5d0734a7
JK
1506 { "(bad)" },
1507 },
1508 /* dc */
1509 {
1510 { "fadd", STi, ST },
1511 { "fmul", STi, ST },
1512 { "(bad)" },
1513 { "(bad)" },
80119c9e 1514#if UNIXWARE_COMPAT
5d0734a7
JK
1515 { "fsub", STi, ST },
1516 { "fsubr", STi, ST },
1517 { "fdiv", STi, ST },
1518 { "fdivr", STi, ST },
80119c9e
ILT
1519#else
1520 { "fsubr", STi, ST },
1521 { "fsub", STi, ST },
1522 { "fdivr", STi, ST },
1523 { "fdiv", STi, ST },
1524#endif
5d0734a7
JK
1525 },
1526 /* dd */
1527 {
1528 { "ffree", STi },
1529 { "(bad)" },
1530 { "fst", STi },
1531 { "fstp", STi },
1532 { "fucom", STi },
1533 { "fucomp", STi },
1534 { "(bad)" },
1535 { "(bad)" },
1536 },
1537 /* de */
1538 {
1539 { "faddp", STi, ST },
1540 { "fmulp", STi, ST },
1541 { "(bad)" },
1542 { FGRPde_3 },
80119c9e 1543#if UNIXWARE_COMPAT
5d0734a7
JK
1544 { "fsubp", STi, ST },
1545 { "fsubrp", STi, ST },
1546 { "fdivp", STi, ST },
1547 { "fdivrp", STi, ST },
80119c9e
ILT
1548#else
1549 { "fsubrp", STi, ST },
1550 { "fsubp", STi, ST },
1551 { "fdivrp", STi, ST },
1552 { "fdivp", STi, ST },
1553#endif
5d0734a7
JK
1554 },
1555 /* df */
1556 {
1557 { "(bad)" },
1558 { "(bad)" },
1559 { "(bad)" },
1560 { "(bad)" },
1561 { FGRPdf_4 },
1d935cf6
MM
1562 { "fucomip",ST, STi },
1563 { "fcomip", ST, STi },
5d0734a7
JK
1564 { "(bad)" },
1565 },
1566};
1567
1568
be0c8b05 1569static char *fgrps[][8] = {
5d0734a7
JK
1570 /* d9_2 0 */
1571 {
1572 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1573 },
1574
1575 /* d9_4 1 */
1576 {
1577 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
1578 },
1579
1580 /* d9_5 2 */
1581 {
1582 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
1583 },
1584
1585 /* d9_6 3 */
1586 {
1587 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
1588 },
1589
1590 /* d9_7 4 */
1591 {
1592 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
1593 },
1594
1595 /* da_5 5 */
1596 {
1597 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1598 },
1599
1600 /* db_4 6 */
1601 {
1602 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
1603 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
1604 },
1605
1606 /* de_3 7 */
1607 {
1608 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1609 },
1610
1611 /* df_4 8 */
1612 {
1613 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1614 },
1615};
1616
1617static void
80119c9e
ILT
1618dofloat (sizeflag)
1619 int sizeflag;
5d0734a7
JK
1620{
1621 struct dis386 *dp;
1622 unsigned char floatop;
1623
1624 floatop = codep[-1];
1625
1626 if (mod != 3)
1627 {
80119c9e 1628 putop (float_mem[(floatop - 0xd8) * 8 + reg], sizeflag);
5d0734a7 1629 obufp = op1out;
80119c9e 1630 OP_E (v_mode, sizeflag);
5d0734a7
JK
1631 return;
1632 }
1633 codep++;
1634
1635 dp = &float_reg[floatop - 0xd8][reg];
1636 if (dp->name == NULL)
1637 {
80119c9e 1638 putop (fgrps[dp->bytemode1][rm], sizeflag);
5d0734a7
JK
1639 /* instruction fnstsw is only one with strange arg */
1640 if (floatop == 0xdf
1641 && FETCH_DATA (the_info, codep + 1)
1642 && *codep == 0xe0)
1643 strcpy (op1out, "%eax");
1644 }
1645 else
1646 {
80119c9e 1647 putop (dp->name, sizeflag);
5d0734a7
JK
1648 obufp = op1out;
1649 if (dp->op1)
80119c9e 1650 (*dp->op1)(dp->bytemode1, sizeflag);
5d0734a7
JK
1651 obufp = op2out;
1652 if (dp->op2)
80119c9e 1653 (*dp->op2)(dp->bytemode2, sizeflag);
5d0734a7
JK
1654 }
1655}
1656
1657/* ARGSUSED */
80119c9e
ILT
1658static void
1659OP_ST (ignore, sizeflag)
5d0734a7 1660 int ignore;
80119c9e 1661 int sizeflag;
5d0734a7
JK
1662{
1663 oappend ("%st");
5d0734a7
JK
1664}
1665
1666/* ARGSUSED */
80119c9e
ILT
1667static void
1668OP_STi (ignore, sizeflag)
5d0734a7 1669 int ignore;
80119c9e 1670 int sizeflag;
5d0734a7
JK
1671{
1672 sprintf (scratchbuf, "%%st(%d)", rm);
1673 oappend (scratchbuf);
5d0734a7
JK
1674}
1675
1676
1677/* capital letters in template are macros */
1678static void
80119c9e 1679putop (template, sizeflag)
5d0734a7 1680 char *template;
80119c9e 1681 int sizeflag;
5d0734a7
JK
1682{
1683 char *p;
1684
1685 for (p = template; *p; p++)
1686 {
1687 switch (*p)
1688 {
1689 default:
1690 *obufp++ = *p;
1691 break;
5f90dab1
ILT
1692 case 'A':
1693 if (mod != 3
1694#ifdef SUFFIX_ALWAYS
1695 || (sizeflag & SUFFIX_ALWAYS)
1696#endif
1697 )
1698 *obufp++ = 'b';
1699 break;
1700 case 'B':
1701#ifdef SUFFIX_ALWAYS
1702 if (sizeflag & SUFFIX_ALWAYS)
1703 *obufp++ = 'b';
1704#endif
1705 break;
1706 case 'E': /* For jcxz/jecxz */
80119c9e 1707 if (sizeflag & AFLAG)
5d0734a7
JK
1708 *obufp++ = 'e';
1709 break;
5f90dab1
ILT
1710 case 'L':
1711#ifdef SUFFIX_ALWAYS
1712 if (sizeflag & SUFFIX_ALWAYS)
1713 *obufp++ = 'l';
1714#endif
1715 break;
5d0734a7
JK
1716 case 'N':
1717 if ((prefixes & PREFIX_FWAIT) == 0)
1718 *obufp++ = 'n';
1719 break;
5f90dab1
ILT
1720 case 'P':
1721 if ((prefixes & PREFIX_DATA)
1722#ifdef SUFFIX_ALWAYS
1723 || (sizeflag & SUFFIX_ALWAYS)
1724#endif
1725 )
1726 {
1727 if (sizeflag & DFLAG)
1728 *obufp++ = 'l';
1729 else
1730 *obufp++ = 'w';
1731 }
1732 break;
1733 case 'Q':
1734 if (mod != 3
1735#ifdef SUFFIX_ALWAYS
1736 || (sizeflag & SUFFIX_ALWAYS)
1737#endif
1738 )
1739 {
1740 if (sizeflag & DFLAG)
1741 *obufp++ = 'l';
1742 else
1743 *obufp++ = 'w';
1744 }
1745 break;
1746 case 'R':
80119c9e 1747 if (sizeflag & DFLAG)
5d0734a7
JK
1748 *obufp++ = 'l';
1749 else
1750 *obufp++ = 'w';
1751 break;
5f90dab1
ILT
1752 case 'S':
1753#ifdef SUFFIX_ALWAYS
1754 if (sizeflag & SUFFIX_ALWAYS)
1755 {
1756 if (sizeflag & DFLAG)
1757 *obufp++ = 'l';
1758 else
1759 *obufp++ = 'w';
1760 }
1761#endif
1762 break;
eedca9da
ILT
1763 case 'W':
1764 /* operand size flag for cwtl, cbtw */
80119c9e 1765 if (sizeflag & DFLAG)
eedca9da
ILT
1766 *obufp++ = 'w';
1767 else
1768 *obufp++ = 'b';
1769 break;
5d0734a7
JK
1770 }
1771 }
1772 *obufp = 0;
1773}
1774
1775static void
1776oappend (s)
1777 char *s;
1778{
1779 strcpy (obufp, s);
1780 obufp += strlen (s);
5d0734a7
JK
1781}
1782
1783static void
80119c9e 1784append_seg ()
5d0734a7
JK
1785{
1786 if (prefixes & PREFIX_CS)
1787 oappend ("%cs:");
1788 if (prefixes & PREFIX_DS)
1789 oappend ("%ds:");
1790 if (prefixes & PREFIX_SS)
1791 oappend ("%ss:");
1792 if (prefixes & PREFIX_ES)
1793 oappend ("%es:");
1794 if (prefixes & PREFIX_FS)
1795 oappend ("%fs:");
1796 if (prefixes & PREFIX_GS)
1797 oappend ("%gs:");
1798}
1799
80119c9e
ILT
1800static void
1801OP_indirE (bytemode, sizeflag)
5d0734a7 1802 int bytemode;
80119c9e 1803 int sizeflag;
5d0734a7
JK
1804{
1805 oappend ("*");
80119c9e 1806 OP_E (bytemode, sizeflag);
5d0734a7
JK
1807}
1808
80119c9e
ILT
1809static void
1810OP_E (bytemode, sizeflag)
5d0734a7 1811 int bytemode;
80119c9e 1812 int sizeflag;
5d0734a7
JK
1813{
1814 int disp;
be0c8b05 1815
5d0734a7
JK
1816 /* skip mod/rm byte */
1817 codep++;
be0c8b05 1818
5d0734a7
JK
1819 if (mod == 3)
1820 {
1821 switch (bytemode)
1822 {
1823 case b_mode:
1824 oappend (names8[rm]);
1825 break;
1826 case w_mode:
1827 oappend (names16[rm]);
1828 break;
1829 case v_mode:
80119c9e 1830 if (sizeflag & DFLAG)
5d0734a7
JK
1831 oappend (names32[rm]);
1832 else
1833 oappend (names16[rm]);
1834 break;
1835 default:
1836 oappend ("<bad dis table>");
1837 break;
1838 }
80119c9e 1839 return;
5d0734a7 1840 }
be0c8b05
SG
1841
1842 disp = 0;
80119c9e 1843 append_seg ();
be0c8b05 1844
80119c9e 1845 if (sizeflag & AFLAG) /* 32 bit address mode */
5d0734a7 1846 {
be0c8b05
SG
1847 int havesib;
1848 int havebase;
1849 int base;
409595b8
ILT
1850 int index = 0;
1851 int scale = 0;
be0c8b05
SG
1852
1853 havesib = 0;
5d0734a7 1854 havebase = 1;
be0c8b05
SG
1855 base = rm;
1856
1857 if (base == 4)
1858 {
1859 havesib = 1;
1860 FETCH_DATA (the_info, codep + 1);
1861 scale = (*codep >> 6) & 3;
1862 index = (*codep >> 3) & 7;
1863 base = *codep & 7;
1864 codep++;
1865 }
1866
1867 switch (mod)
5d0734a7 1868 {
be0c8b05
SG
1869 case 0:
1870 if (base == 5)
1871 {
1872 havebase = 0;
1873 disp = get32 ();
1874 }
5d0734a7 1875 break;
be0c8b05
SG
1876 case 1:
1877 FETCH_DATA (the_info, codep + 1);
409595b8
ILT
1878 disp = *codep++;
1879 if ((disp & 0x80) != 0)
1880 disp -= 0x100;
5d0734a7 1881 break;
be0c8b05
SG
1882 case 2:
1883 disp = get32 ();
5d0734a7
JK
1884 break;
1885 }
be0c8b05
SG
1886
1887 if (mod != 0 || base == 5)
5d0734a7 1888 {
be0c8b05
SG
1889 sprintf (scratchbuf, "0x%x", disp);
1890 oappend (scratchbuf);
5d0734a7 1891 }
be0c8b05
SG
1892
1893 if (havebase || (havesib && (index != 4 || scale != 0)))
5d0734a7 1894 {
be0c8b05
SG
1895 oappend ("(");
1896 if (havebase)
1897 oappend (names32[base]);
1898 if (havesib)
5d0734a7 1899 {
be0c8b05
SG
1900 if (index != 4)
1901 {
1902 sprintf (scratchbuf, ",%s", names32[index]);
1903 oappend (scratchbuf);
1904 }
1905 sprintf (scratchbuf, ",%d", 1 << scale);
5d0734a7
JK
1906 oappend (scratchbuf);
1907 }
be0c8b05
SG
1908 oappend (")");
1909 }
1910 }
1911 else
1912 { /* 16 bit address mode */
1913 switch (mod)
1914 {
1915 case 0:
1916 if (rm == 6)
409595b8
ILT
1917 {
1918 disp = get16 ();
1919 if ((disp & 0x8000) != 0)
1920 disp -= 0x10000;
1921 }
be0c8b05
SG
1922 break;
1923 case 1:
1924 FETCH_DATA (the_info, codep + 1);
409595b8
ILT
1925 disp = *codep++;
1926 if ((disp & 0x80) != 0)
1927 disp -= 0x100;
be0c8b05
SG
1928 break;
1929 case 2:
409595b8
ILT
1930 disp = get16 ();
1931 if ((disp & 0x8000) != 0)
1932 disp -= 0x10000;
be0c8b05
SG
1933 break;
1934 }
1935
1936 if (mod != 0 || rm == 6)
1937 {
1938 sprintf (scratchbuf, "0x%x", disp);
5d0734a7
JK
1939 oappend (scratchbuf);
1940 }
be0c8b05
SG
1941
1942 if (mod != 0 || rm != 6)
1943 {
1944 oappend ("(");
1945 oappend (index16[rm]);
1946 oappend (")");
1947 }
5d0734a7 1948 }
5d0734a7
JK
1949}
1950
80119c9e
ILT
1951#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
1952
1953static void
1954OP_G (bytemode, sizeflag)
5d0734a7 1955 int bytemode;
80119c9e 1956 int sizeflag;
5d0734a7
JK
1957{
1958 switch (bytemode)
1959 {
1960 case b_mode:
1961 oappend (names8[reg]);
1962 break;
1963 case w_mode:
1964 oappend (names16[reg]);
1965 break;
1966 case d_mode:
1967 oappend (names32[reg]);
1968 break;
1969 case v_mode:
80119c9e 1970 if (sizeflag & DFLAG)
5d0734a7
JK
1971 oappend (names32[reg]);
1972 else
1973 oappend (names16[reg]);
1974 break;
1975 default:
80119c9e 1976 oappend (INTERNAL_DISASSEMBLER_ERROR);
5d0734a7
JK
1977 break;
1978 }
5d0734a7
JK
1979}
1980
1981static int
1982get32 ()
1983{
1984 int x = 0;
1985
1986 FETCH_DATA (the_info, codep + 4);
1987 x = *codep++ & 0xff;
1988 x |= (*codep++ & 0xff) << 8;
1989 x |= (*codep++ & 0xff) << 16;
1990 x |= (*codep++ & 0xff) << 24;
80119c9e 1991 return x;
5d0734a7
JK
1992}
1993
1994static int
1995get16 ()
1996{
1997 int x = 0;
1998
1999 FETCH_DATA (the_info, codep + 2);
2000 x = *codep++ & 0xff;
2001 x |= (*codep++ & 0xff) << 8;
80119c9e 2002 return x;
5d0734a7
JK
2003}
2004
2005static void
2006set_op (op)
80ade993 2007 unsigned int op;
5d0734a7
JK
2008{
2009 op_index[op_ad] = op_ad;
2010 op_address[op_ad] = op;
2011}
2012
80119c9e
ILT
2013static void
2014OP_REG (code, sizeflag)
5d0734a7 2015 int code;
80119c9e 2016 int sizeflag;
5d0734a7
JK
2017{
2018 char *s;
2019
2020 switch (code)
2021 {
2022 case indir_dx_reg: s = "(%dx)"; break;
2023 case ax_reg: case cx_reg: case dx_reg: case bx_reg:
2024 case sp_reg: case bp_reg: case si_reg: case di_reg:
2025 s = names16[code - ax_reg];
2026 break;
2027 case es_reg: case ss_reg: case cs_reg:
2028 case ds_reg: case fs_reg: case gs_reg:
2029 s = names_seg[code - es_reg];
2030 break;
2031 case al_reg: case ah_reg: case cl_reg: case ch_reg:
2032 case dl_reg: case dh_reg: case bl_reg: case bh_reg:
2033 s = names8[code - al_reg];
2034 break;
2035 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
2036 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
80119c9e 2037 if (sizeflag & DFLAG)
5d0734a7
JK
2038 s = names32[code - eAX_reg];
2039 else
2040 s = names16[code - eAX_reg];
2041 break;
2042 default:
80119c9e 2043 s = INTERNAL_DISASSEMBLER_ERROR;
5d0734a7
JK
2044 break;
2045 }
2046 oappend (s);
5d0734a7
JK
2047}
2048
80119c9e
ILT
2049static void
2050OP_I (bytemode, sizeflag)
5d0734a7 2051 int bytemode;
80119c9e 2052 int sizeflag;
5d0734a7
JK
2053{
2054 int op;
2055
2056 switch (bytemode)
2057 {
2058 case b_mode:
2059 FETCH_DATA (the_info, codep + 1);
2060 op = *codep++ & 0xff;
2061 break;
2062 case v_mode:
80119c9e 2063 if (sizeflag & DFLAG)
5d0734a7
JK
2064 op = get32 ();
2065 else
2066 op = get16 ();
2067 break;
2068 case w_mode:
2069 op = get16 ();
2070 break;
2071 default:
80119c9e
ILT
2072 oappend (INTERNAL_DISASSEMBLER_ERROR);
2073 return;
5d0734a7
JK
2074 }
2075 sprintf (scratchbuf, "$0x%x", op);
2076 oappend (scratchbuf);
5d0734a7
JK
2077}
2078
80119c9e
ILT
2079static void
2080OP_sI (bytemode, sizeflag)
5d0734a7 2081 int bytemode;
80119c9e 2082 int sizeflag;
5d0734a7
JK
2083{
2084 int op;
2085
2086 switch (bytemode)
2087 {
2088 case b_mode:
2089 FETCH_DATA (the_info, codep + 1);
409595b8
ILT
2090 op = *codep++;
2091 if ((op & 0x80) != 0)
2092 op -= 0x100;
5d0734a7
JK
2093 break;
2094 case v_mode:
80119c9e 2095 if (sizeflag & DFLAG)
5d0734a7
JK
2096 op = get32 ();
2097 else
409595b8
ILT
2098 {
2099 op = get16();
2100 if ((op & 0x8000) != 0)
2101 op -= 0x10000;
2102 }
5d0734a7
JK
2103 break;
2104 case w_mode:
409595b8
ILT
2105 op = get16 ();
2106 if ((op & 0x8000) != 0)
2107 op -= 0x10000;
5d0734a7
JK
2108 break;
2109 default:
80119c9e
ILT
2110 oappend (INTERNAL_DISASSEMBLER_ERROR);
2111 return;
5d0734a7
JK
2112 }
2113 sprintf (scratchbuf, "$0x%x", op);
2114 oappend (scratchbuf);
5d0734a7
JK
2115}
2116
80119c9e
ILT
2117static void
2118OP_J (bytemode, sizeflag)
5d0734a7 2119 int bytemode;
80119c9e 2120 int sizeflag;
5d0734a7
JK
2121{
2122 int disp;
2123 int mask = -1;
2124
2125 switch (bytemode)
2126 {
2127 case b_mode:
2128 FETCH_DATA (the_info, codep + 1);
409595b8
ILT
2129 disp = *codep++;
2130 if ((disp & 0x80) != 0)
2131 disp -= 0x100;
5d0734a7
JK
2132 break;
2133 case v_mode:
80119c9e 2134 if (sizeflag & DFLAG)
5d0734a7
JK
2135 disp = get32 ();
2136 else
2137 {
409595b8
ILT
2138 disp = get16 ();
2139 if ((disp & 0x8000) != 0)
2140 disp -= 0x10000;
5d0734a7
JK
2141 /* for some reason, a data16 prefix on a jump instruction
2142 means that the pc is masked to 16 bits after the
2143 displacement is added! */
2144 mask = 0xffff;
2145 }
2146 break;
2147 default:
80119c9e
ILT
2148 oappend (INTERNAL_DISASSEMBLER_ERROR);
2149 return;
5d0734a7
JK
2150 }
2151 disp = (start_pc + codep - start_codep + disp) & mask;
2152 set_op (disp);
2153 sprintf (scratchbuf, "0x%x", disp);
2154 oappend (scratchbuf);
5d0734a7
JK
2155}
2156
2157/* ARGSUSED */
80119c9e
ILT
2158static void
2159OP_SEG (dummy, sizeflag)
5d0734a7 2160 int dummy;
80119c9e 2161 int sizeflag;
5d0734a7
JK
2162{
2163 static char *sreg[] = {
2164 "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
2165 };
2166
2167 oappend (sreg[reg]);
5d0734a7
JK
2168}
2169
80119c9e
ILT
2170static void
2171OP_DIR (size, sizeflag)
5d0734a7 2172 int size;
80119c9e 2173 int sizeflag;
5d0734a7
JK
2174{
2175 int seg, offset;
2176
2177 switch (size)
2178 {
2179 case lptr:
80119c9e 2180 if (sizeflag & DFLAG)
5d0734a7
JK
2181 {
2182 offset = get32 ();
2183 seg = get16 ();
2184 }
2185 else
2186 {
2187 offset = get16 ();
2188 seg = get16 ();
2189 }
5f90dab1 2190 sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
5d0734a7
JK
2191 oappend (scratchbuf);
2192 break;
2193 case v_mode:
80119c9e 2194 if (sizeflag & DFLAG)
5d0734a7
JK
2195 offset = get32 ();
2196 else
409595b8
ILT
2197 {
2198 offset = get16 ();
2199 if ((offset & 0x8000) != 0)
2200 offset -= 0x10000;
2201 }
5d0734a7
JK
2202
2203 offset = start_pc + codep - start_codep + offset;
2204 set_op (offset);
2205 sprintf (scratchbuf, "0x%x", offset);
2206 oappend (scratchbuf);
2207 break;
2208 default:
80119c9e 2209 oappend (INTERNAL_DISASSEMBLER_ERROR);
5d0734a7
JK
2210 break;
2211 }
5d0734a7
JK
2212}
2213
2214/* ARGSUSED */
80119c9e
ILT
2215static void
2216OP_OFF (ignore, sizeflag)
2217 int ignore;
2218 int sizeflag;
5d0734a7
JK
2219{
2220 int off;
be0c8b05 2221
80119c9e 2222 append_seg ();
be0c8b05 2223
80119c9e 2224 if (sizeflag & AFLAG)
5d0734a7
JK
2225 off = get32 ();
2226 else
2227 off = get16 ();
2228
2229 sprintf (scratchbuf, "0x%x", off);
2230 oappend (scratchbuf);
5d0734a7
JK
2231}
2232
80119c9e
ILT
2233static void
2234ptr_reg (code, sizeflag)
2235 int code;
2236 int sizeflag;
5d0734a7 2237{
80119c9e
ILT
2238 char *s;
2239 oappend ("(");
2240 if (sizeflag & AFLAG)
2241 s = names32[code - eAX_reg];
2242 else
2243 s = names16[code - eAX_reg];
2244 oappend (s);
5d0734a7 2245 oappend (")");
5d0734a7
JK
2246}
2247
80119c9e
ILT
2248static void
2249OP_ESreg (code, sizeflag)
2250 int code;
2251 int sizeflag;
2252{
2253 oappend ("%es:");
2254 ptr_reg (code, sizeflag);
2255}
2256
2257static void
2258OP_DSreg (code, sizeflag)
2259 int code;
2260 int sizeflag;
5d0734a7 2261{
409595b8
ILT
2262 if ((prefixes
2263 & (PREFIX_CS
2264 | PREFIX_DS
2265 | PREFIX_SS
2266 | PREFIX_ES
2267 | PREFIX_FS
2268 | PREFIX_GS)) == 0)
2269 prefixes |= PREFIX_DS;
80119c9e
ILT
2270 append_seg();
2271 ptr_reg (code, sizeflag);
5d0734a7
JK
2272}
2273
41b96d55
ILT
2274#if 0
2275/* Not used. */
2276
5d0734a7 2277/* ARGSUSED */
80119c9e
ILT
2278static void
2279OP_ONE (dummy, sizeflag)
be0c8b05 2280 int dummy;
80119c9e 2281 int sizeflag;
5d0734a7
JK
2282{
2283 oappend ("1");
5d0734a7
JK
2284}
2285
41b96d55
ILT
2286#endif
2287
5d0734a7 2288/* ARGSUSED */
80119c9e
ILT
2289static void
2290OP_C (dummy, sizeflag)
be0c8b05 2291 int dummy;
80119c9e 2292 int sizeflag;
5d0734a7
JK
2293{
2294 codep++; /* skip mod/rm */
2295 sprintf (scratchbuf, "%%cr%d", reg);
2296 oappend (scratchbuf);
5d0734a7
JK
2297}
2298
2299/* ARGSUSED */
80119c9e
ILT
2300static void
2301OP_D (dummy, sizeflag)
be0c8b05 2302 int dummy;
80119c9e 2303 int sizeflag;
5d0734a7
JK
2304{
2305 codep++; /* skip mod/rm */
2306 sprintf (scratchbuf, "%%db%d", reg);
2307 oappend (scratchbuf);
5d0734a7
JK
2308}
2309
2310/* ARGSUSED */
80119c9e
ILT
2311static void
2312OP_T (dummy, sizeflag)
5d0734a7 2313 int dummy;
80119c9e 2314 int sizeflag;
5d0734a7
JK
2315{
2316 codep++; /* skip mod/rm */
2317 sprintf (scratchbuf, "%%tr%d", reg);
2318 oappend (scratchbuf);
5d0734a7
JK
2319}
2320
80119c9e
ILT
2321static void
2322OP_rm (bytemode, sizeflag)
5d0734a7 2323 int bytemode;
80119c9e 2324 int sizeflag;
5d0734a7
JK
2325{
2326 switch (bytemode)
2327 {
2328 case d_mode:
2329 oappend (names32[rm]);
2330 break;
2331 case w_mode:
2332 oappend (names16[rm]);
2333 break;
2334 }
5d0734a7 2335}
eedca9da 2336
80119c9e
ILT
2337static void
2338OP_MMX (ignore, sizeflag)
2339 int ignore;
2340 int sizeflag;
eedca9da
ILT
2341{
2342 sprintf (scratchbuf, "%%mm%d", reg);
2343 oappend (scratchbuf);
eedca9da
ILT
2344}
2345
80119c9e
ILT
2346static void
2347OP_EM (bytemode, sizeflag)
eedca9da 2348 int bytemode;
80119c9e 2349 int sizeflag;
eedca9da
ILT
2350{
2351 if (mod != 3)
80119c9e
ILT
2352 {
2353 OP_E (bytemode, sizeflag);
2354 return;
2355 }
eedca9da
ILT
2356
2357 codep++;
2358 sprintf (scratchbuf, "%%mm%d", rm);
2359 oappend (scratchbuf);
eedca9da
ILT
2360}
2361
80119c9e
ILT
2362static void
2363OP_MS (ignore, sizeflag)
2364 int ignore;
2365 int sizeflag;
eedca9da
ILT
2366{
2367 ++codep;
2368 sprintf (scratchbuf, "%%mm%d", rm);
2369 oappend (scratchbuf);
eedca9da 2370}
This page took 0.330241 seconds and 4 git commands to generate.