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