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