Tue Nov 5 10:30:51 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
[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 1036{
d9ad578c
SG
1037 if (info->mach == bfd_mach_i386_i386)
1038 print_insn_x86 (pc, info, 1, 1);
1039 else if (info->mach == bfd_mach_i386_i8086)
1040 print_insn_x86 (pc, info, 0, 0);
1041 else
1042 abort ();
be0c8b05
SG
1043}
1044
1045int
1046print_insn_x86 (pc, info, aflag, dflag)
1047 bfd_vma pc;
1048 disassemble_info *info;
5d0734a7
JK
1049{
1050 struct dis386 *dp;
1051 int i;
1052 int enter_instruction;
1053 char *first, *second, *third;
1054 int needcomma;
03db5a93
ILT
1055 unsigned char need_modrm;
1056
726257a8 1057 struct dis_private priv;
5d0734a7
JK
1058 bfd_byte *inbuf = priv.the_buffer;
1059
1060 info->private_data = (PTR) &priv;
1061 priv.max_fetched = priv.the_buffer;
1062 priv.insn_start = pc;
1063 if (setjmp (priv.bailout) != 0)
1064 /* Error return. */
1065 return -1;
1066
1067 obuf[0] = 0;
1068 op1out[0] = 0;
1069 op2out[0] = 0;
1070 op3out[0] = 0;
1071
1072 op_index[0] = op_index[1] = op_index[2] = -1;
1073
1074 the_info = info;
1075 start_pc = pc;
1076 start_codep = inbuf;
1077 codep = inbuf;
1078
1079 ckprefix ();
1080
1081 FETCH_DATA (info, codep + 1);
1082 if (*codep == 0xc8)
1083 enter_instruction = 1;
1084 else
1085 enter_instruction = 0;
1086
1087 obufp = obuf;
1088
1089 if (prefixes & PREFIX_REPZ)
1090 oappend ("repz ");
1091 if (prefixes & PREFIX_REPNZ)
1092 oappend ("repnz ");
1093 if (prefixes & PREFIX_LOCK)
1094 oappend ("lock ");
1095
1096 if ((prefixes & PREFIX_FWAIT)
1097 && ((*codep < 0xd8) || (*codep > 0xdf)))
1098 {
1099 /* fwait not followed by floating point instruction */
1100 (*info->fprintf_func) (info->stream, "fwait");
1101 return (1);
1102 }
1103
5d0734a7
JK
1104 if (prefixes & PREFIX_DATA)
1105 dflag ^= 1;
1106
1107 if (prefixes & PREFIX_ADR)
1108 {
1109 aflag ^= 1;
1110 oappend ("addr16 ");
1111 }
1112
1113 if (*codep == 0x0f)
1114 {
1115 FETCH_DATA (info, codep + 2);
1116 dp = &dis386_twobyte[*++codep];
03db5a93 1117 need_modrm = twobyte_has_modrm[*codep];
5d0734a7
JK
1118 }
1119 else
03db5a93
ILT
1120 {
1121 dp = &dis386[*codep];
1122 need_modrm = onebyte_has_modrm[*codep];
1123 }
5d0734a7 1124 codep++;
5c9b5f58 1125
03db5a93
ILT
1126 if (need_modrm)
1127 {
1128 FETCH_DATA (info, codep + 1);
1129 mod = (*codep >> 6) & 3;
1130 reg = (*codep >> 3) & 7;
1131 rm = *codep & 7;
1132 }
5c9b5f58 1133
5d0734a7
JK
1134 if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
1135 {
be0c8b05 1136 dofloat (aflag, dflag);
5d0734a7
JK
1137 }
1138 else
1139 {
1140 if (dp->name == NULL)
1141 dp = &grps[dp->bytemode1][reg];
1142
be0c8b05 1143 putop (dp->name, aflag, dflag);
5d0734a7
JK
1144
1145 obufp = op1out;
1146 op_ad = 2;
1147 if (dp->op1)
be0c8b05 1148 (*dp->op1)(dp->bytemode1, aflag, dflag);
5d0734a7
JK
1149
1150 obufp = op2out;
1151 op_ad = 1;
1152 if (dp->op2)
be0c8b05 1153 (*dp->op2)(dp->bytemode2, aflag, dflag);
5d0734a7
JK
1154
1155 obufp = op3out;
1156 op_ad = 0;
1157 if (dp->op3)
be0c8b05 1158 (*dp->op3)(dp->bytemode3, aflag, dflag);
5d0734a7
JK
1159 }
1160
1161 obufp = obuf + strlen (obuf);
1162 for (i = strlen (obuf); i < 6; i++)
1163 oappend (" ");
1164 oappend (" ");
1165 (*info->fprintf_func) (info->stream, "%s", obuf);
1166
1167 /* enter instruction is printed with operands in the
1168 * same order as the intel book; everything else
1169 * is printed in reverse order
1170 */
1171 if (enter_instruction)
1172 {
1173 first = op1out;
1174 second = op2out;
1175 third = op3out;
1176 op_ad = op_index[0];
1177 op_index[0] = op_index[2];
1178 op_index[2] = op_ad;
1179 }
1180 else
1181 {
1182 first = op3out;
1183 second = op2out;
1184 third = op1out;
1185 }
1186 needcomma = 0;
1187 if (*first)
1188 {
1189 if (op_index[0] != -1)
a279b1f5 1190 (*info->print_address_func) (op_address[op_index[0]], info);
5d0734a7
JK
1191 else
1192 (*info->fprintf_func) (info->stream, "%s", first);
1193 needcomma = 1;
1194 }
1195 if (*second)
1196 {
1197 if (needcomma)
1198 (*info->fprintf_func) (info->stream, ",");
1199 if (op_index[1] != -1)
a279b1f5 1200 (*info->print_address_func) (op_address[op_index[1]], info);
5d0734a7
JK
1201 else
1202 (*info->fprintf_func) (info->stream, "%s", second);
1203 needcomma = 1;
1204 }
1205 if (*third)
1206 {
1207 if (needcomma)
1208 (*info->fprintf_func) (info->stream, ",");
1209 if (op_index[2] != -1)
a279b1f5 1210 (*info->print_address_func) (op_address[op_index[2]], info);
5d0734a7
JK
1211 else
1212 (*info->fprintf_func) (info->stream, "%s", third);
1213 }
1214 return (codep - inbuf);
1215}
1216
be0c8b05 1217static char *float_mem[] = {
5d0734a7
JK
1218 /* d8 */
1219 "fadds",
1220 "fmuls",
1221 "fcoms",
1222 "fcomps",
1223 "fsubs",
1224 "fsubrs",
1225 "fdivs",
1226 "fdivrs",
1227 /* d9 */
1228 "flds",
1229 "(bad)",
1230 "fsts",
1231 "fstps",
1232 "fldenv",
1233 "fldcw",
1234 "fNstenv",
1235 "fNstcw",
1236 /* da */
1237 "fiaddl",
1238 "fimull",
1239 "ficoml",
1240 "ficompl",
1241 "fisubl",
1242 "fisubrl",
1243 "fidivl",
1244 "fidivrl",
1245 /* db */
1246 "fildl",
1247 "(bad)",
1248 "fistl",
1249 "fistpl",
1250 "(bad)",
1251 "fldt",
1252 "(bad)",
1253 "fstpt",
1254 /* dc */
1255 "faddl",
1256 "fmull",
1257 "fcoml",
1258 "fcompl",
1259 "fsubl",
1260 "fsubrl",
1261 "fdivl",
1262 "fdivrl",
1263 /* dd */
1264 "fldl",
1265 "(bad)",
1266 "fstl",
1267 "fstpl",
1268 "frstor",
1269 "(bad)",
1270 "fNsave",
1271 "fNstsw",
1272 /* de */
1273 "fiadd",
1274 "fimul",
1275 "ficom",
1276 "ficomp",
1277 "fisub",
1278 "fisubr",
1279 "fidiv",
1280 "fidivr",
1281 /* df */
1282 "fild",
1283 "(bad)",
1284 "fist",
1285 "fistp",
1286 "fbld",
1287 "fildll",
1288 "fbstp",
1289 "fistpll",
1290};
1291
1292#define ST OP_ST, 0
1293#define STi OP_STi, 0
5d0734a7
JK
1294
1295#define FGRPd9_2 NULL, NULL, 0
1296#define FGRPd9_4 NULL, NULL, 1
1297#define FGRPd9_5 NULL, NULL, 2
1298#define FGRPd9_6 NULL, NULL, 3
1299#define FGRPd9_7 NULL, NULL, 4
1300#define FGRPda_5 NULL, NULL, 5
1301#define FGRPdb_4 NULL, NULL, 6
1302#define FGRPde_3 NULL, NULL, 7
1303#define FGRPdf_4 NULL, NULL, 8
1304
be0c8b05 1305static struct dis386 float_reg[][8] = {
5d0734a7
JK
1306 /* d8 */
1307 {
1308 { "fadd", ST, STi },
1309 { "fmul", ST, STi },
1310 { "fcom", STi },
1311 { "fcomp", STi },
1312 { "fsub", ST, STi },
1313 { "fsubr", ST, STi },
1314 { "fdiv", ST, STi },
1315 { "fdivr", ST, STi },
1316 },
1317 /* d9 */
1318 {
1319 { "fld", STi },
1320 { "fxch", STi },
1321 { FGRPd9_2 },
1322 { "(bad)" },
1323 { FGRPd9_4 },
1324 { FGRPd9_5 },
1325 { FGRPd9_6 },
1326 { FGRPd9_7 },
1327 },
1328 /* da */
1329 {
1d935cf6
MM
1330 { "fcmovb", ST, STi },
1331 { "fcmove", ST, STi },
1332 { "fcmovbe",ST, STi },
1333 { "fcmovu", ST, STi },
5d0734a7
JK
1334 { "(bad)" },
1335 { FGRPda_5 },
1336 { "(bad)" },
1337 { "(bad)" },
1338 },
1339 /* db */
1340 {
1d935cf6
MM
1341 { "fcmovnb",ST, STi },
1342 { "fcmovne",ST, STi },
1343 { "fcmovnbe",ST, STi },
1344 { "fcmovnu",ST, STi },
5d0734a7 1345 { FGRPdb_4 },
1d935cf6
MM
1346 { "fucomi", ST, STi },
1347 { "fcomi", ST, STi },
5d0734a7
JK
1348 { "(bad)" },
1349 },
1350 /* dc */
1351 {
1352 { "fadd", STi, ST },
1353 { "fmul", STi, ST },
1354 { "(bad)" },
1355 { "(bad)" },
1356 { "fsub", STi, ST },
1357 { "fsubr", STi, ST },
1358 { "fdiv", STi, ST },
1359 { "fdivr", STi, ST },
1360 },
1361 /* dd */
1362 {
1363 { "ffree", STi },
1364 { "(bad)" },
1365 { "fst", STi },
1366 { "fstp", STi },
1367 { "fucom", STi },
1368 { "fucomp", STi },
1369 { "(bad)" },
1370 { "(bad)" },
1371 },
1372 /* de */
1373 {
1374 { "faddp", STi, ST },
1375 { "fmulp", STi, ST },
1376 { "(bad)" },
1377 { FGRPde_3 },
1378 { "fsubp", STi, ST },
1379 { "fsubrp", STi, ST },
1380 { "fdivp", STi, ST },
1381 { "fdivrp", STi, ST },
1382 },
1383 /* df */
1384 {
1385 { "(bad)" },
1386 { "(bad)" },
1387 { "(bad)" },
1388 { "(bad)" },
1389 { FGRPdf_4 },
1d935cf6
MM
1390 { "fucomip",ST, STi },
1391 { "fcomip", ST, STi },
5d0734a7
JK
1392 { "(bad)" },
1393 },
1394};
1395
1396
be0c8b05 1397static char *fgrps[][8] = {
5d0734a7
JK
1398 /* d9_2 0 */
1399 {
1400 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1401 },
1402
1403 /* d9_4 1 */
1404 {
1405 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
1406 },
1407
1408 /* d9_5 2 */
1409 {
1410 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
1411 },
1412
1413 /* d9_6 3 */
1414 {
1415 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
1416 },
1417
1418 /* d9_7 4 */
1419 {
1420 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
1421 },
1422
1423 /* da_5 5 */
1424 {
1425 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1426 },
1427
1428 /* db_4 6 */
1429 {
1430 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
1431 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
1432 },
1433
1434 /* de_3 7 */
1435 {
1436 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1437 },
1438
1439 /* df_4 8 */
1440 {
1441 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1442 },
1443};
1444
1445static void
be0c8b05
SG
1446dofloat (aflag, dflag)
1447 int aflag;
1448 int dflag;
5d0734a7
JK
1449{
1450 struct dis386 *dp;
1451 unsigned char floatop;
1452
1453 floatop = codep[-1];
1454
1455 if (mod != 3)
1456 {
be0c8b05 1457 putop (float_mem[(floatop - 0xd8) * 8 + reg], aflag, dflag);
5d0734a7 1458 obufp = op1out;
be0c8b05 1459 OP_E (v_mode, aflag, dflag);
5d0734a7
JK
1460 return;
1461 }
1462 codep++;
1463
1464 dp = &float_reg[floatop - 0xd8][reg];
1465 if (dp->name == NULL)
1466 {
be0c8b05 1467 putop (fgrps[dp->bytemode1][rm], aflag, dflag);
5d0734a7
JK
1468 /* instruction fnstsw is only one with strange arg */
1469 if (floatop == 0xdf
1470 && FETCH_DATA (the_info, codep + 1)
1471 && *codep == 0xe0)
1472 strcpy (op1out, "%eax");
1473 }
1474 else
1475 {
be0c8b05 1476 putop (dp->name, aflag, dflag);
5d0734a7
JK
1477 obufp = op1out;
1478 if (dp->op1)
be0c8b05 1479 (*dp->op1)(dp->bytemode1, aflag, dflag);
5d0734a7
JK
1480 obufp = op2out;
1481 if (dp->op2)
be0c8b05 1482 (*dp->op2)(dp->bytemode2, aflag, dflag);
5d0734a7
JK
1483 }
1484}
1485
1486/* ARGSUSED */
be0c8b05
SG
1487static int
1488OP_ST (ignore, aflag, dflag)
5d0734a7 1489 int ignore;
be0c8b05
SG
1490 int aflag;
1491 int dflag;
5d0734a7
JK
1492{
1493 oappend ("%st");
1494 return (0);
1495}
1496
1497/* ARGSUSED */
be0c8b05
SG
1498static int
1499OP_STi (ignore, aflag, dflag)
5d0734a7 1500 int ignore;
be0c8b05
SG
1501 int aflag;
1502 int dflag;
5d0734a7
JK
1503{
1504 sprintf (scratchbuf, "%%st(%d)", rm);
1505 oappend (scratchbuf);
1506 return (0);
1507}
1508
1509
1510/* capital letters in template are macros */
1511static void
be0c8b05 1512putop (template, aflag, dflag)
5d0734a7 1513 char *template;
be0c8b05
SG
1514 int aflag;
1515 int dflag;
5d0734a7
JK
1516{
1517 char *p;
1518
1519 for (p = template; *p; p++)
1520 {
1521 switch (*p)
1522 {
1523 default:
1524 *obufp++ = *p;
1525 break;
1526 case 'C': /* For jcxz/jecxz */
be0c8b05 1527 if (aflag)
5d0734a7
JK
1528 *obufp++ = 'e';
1529 break;
1530 case 'N':
1531 if ((prefixes & PREFIX_FWAIT) == 0)
1532 *obufp++ = 'n';
1533 break;
1534 case 'S':
1535 /* operand size flag */
1536 if (dflag)
1537 *obufp++ = 'l';
1538 else
1539 *obufp++ = 'w';
1540 break;
1541 }
1542 }
1543 *obufp = 0;
1544}
1545
1546static void
1547oappend (s)
1548 char *s;
1549{
1550 strcpy (obufp, s);
1551 obufp += strlen (s);
1552 *obufp = 0;
1553}
1554
1555static void
1556append_prefix ()
1557{
1558 if (prefixes & PREFIX_CS)
1559 oappend ("%cs:");
1560 if (prefixes & PREFIX_DS)
1561 oappend ("%ds:");
1562 if (prefixes & PREFIX_SS)
1563 oappend ("%ss:");
1564 if (prefixes & PREFIX_ES)
1565 oappend ("%es:");
1566 if (prefixes & PREFIX_FS)
1567 oappend ("%fs:");
1568 if (prefixes & PREFIX_GS)
1569 oappend ("%gs:");
1570}
1571
be0c8b05
SG
1572static int
1573OP_indirE (bytemode, aflag, dflag)
5d0734a7 1574 int bytemode;
be0c8b05
SG
1575 int aflag;
1576 int dflag;
5d0734a7
JK
1577{
1578 oappend ("*");
be0c8b05 1579 return OP_E (bytemode, aflag, dflag);
5d0734a7
JK
1580}
1581
be0c8b05
SG
1582static int
1583OP_E (bytemode, aflag, dflag)
5d0734a7 1584 int bytemode;
be0c8b05
SG
1585 int aflag;
1586 int dflag;
5d0734a7
JK
1587{
1588 int disp;
be0c8b05 1589
5d0734a7
JK
1590 /* skip mod/rm byte */
1591 codep++;
be0c8b05 1592
5d0734a7
JK
1593 if (mod == 3)
1594 {
1595 switch (bytemode)
1596 {
1597 case b_mode:
1598 oappend (names8[rm]);
1599 break;
1600 case w_mode:
1601 oappend (names16[rm]);
1602 break;
1603 case v_mode:
1604 if (dflag)
1605 oappend (names32[rm]);
1606 else
1607 oappend (names16[rm]);
1608 break;
1609 default:
1610 oappend ("<bad dis table>");
1611 break;
1612 }
be0c8b05 1613 return 0;
5d0734a7 1614 }
be0c8b05
SG
1615
1616 disp = 0;
5d0734a7 1617 append_prefix ();
be0c8b05
SG
1618
1619 if (aflag) /* 32 bit address mode */
5d0734a7 1620 {
be0c8b05
SG
1621 int havesib;
1622 int havebase;
1623 int base;
1624 int index;
1625 int scale;
1626
1627 havesib = 0;
5d0734a7 1628 havebase = 1;
be0c8b05
SG
1629 base = rm;
1630
1631 if (base == 4)
1632 {
1633 havesib = 1;
1634 FETCH_DATA (the_info, codep + 1);
1635 scale = (*codep >> 6) & 3;
1636 index = (*codep >> 3) & 7;
1637 base = *codep & 7;
1638 codep++;
1639 }
1640
1641 switch (mod)
5d0734a7 1642 {
be0c8b05
SG
1643 case 0:
1644 if (base == 5)
1645 {
1646 havebase = 0;
1647 disp = get32 ();
1648 }
5d0734a7 1649 break;
be0c8b05
SG
1650 case 1:
1651 FETCH_DATA (the_info, codep + 1);
1652 disp = *(char *)codep++;
5d0734a7 1653 break;
be0c8b05
SG
1654 case 2:
1655 disp = get32 ();
5d0734a7
JK
1656 break;
1657 }
be0c8b05
SG
1658
1659 if (mod != 0 || base == 5)
5d0734a7 1660 {
be0c8b05
SG
1661 sprintf (scratchbuf, "0x%x", disp);
1662 oappend (scratchbuf);
5d0734a7 1663 }
be0c8b05
SG
1664
1665 if (havebase || (havesib && (index != 4 || scale != 0)))
5d0734a7 1666 {
be0c8b05
SG
1667 oappend ("(");
1668 if (havebase)
1669 oappend (names32[base]);
1670 if (havesib)
5d0734a7 1671 {
be0c8b05
SG
1672 if (index != 4)
1673 {
1674 sprintf (scratchbuf, ",%s", names32[index]);
1675 oappend (scratchbuf);
1676 }
1677 sprintf (scratchbuf, ",%d", 1 << scale);
5d0734a7
JK
1678 oappend (scratchbuf);
1679 }
be0c8b05
SG
1680 oappend (")");
1681 }
1682 }
1683 else
1684 { /* 16 bit address mode */
1685 switch (mod)
1686 {
1687 case 0:
1688 if (rm == 6)
1689 disp = (short) get16 ();
1690 break;
1691 case 1:
1692 FETCH_DATA (the_info, codep + 1);
1693 disp = *(char *)codep++;
1694 break;
1695 case 2:
1696 disp = (short) get16 ();
1697 break;
1698 }
1699
1700 if (mod != 0 || rm == 6)
1701 {
1702 sprintf (scratchbuf, "0x%x", disp);
5d0734a7
JK
1703 oappend (scratchbuf);
1704 }
be0c8b05
SG
1705
1706 if (mod != 0 || rm != 6)
1707 {
1708 oappend ("(");
1709 oappend (index16[rm]);
1710 oappend (")");
1711 }
5d0734a7 1712 }
be0c8b05 1713 return 0;
5d0734a7
JK
1714}
1715
be0c8b05
SG
1716static int
1717OP_G (bytemode, aflag, dflag)
5d0734a7 1718 int bytemode;
be0c8b05
SG
1719 int aflag;
1720 int dflag;
5d0734a7
JK
1721{
1722 switch (bytemode)
1723 {
1724 case b_mode:
1725 oappend (names8[reg]);
1726 break;
1727 case w_mode:
1728 oappend (names16[reg]);
1729 break;
1730 case d_mode:
1731 oappend (names32[reg]);
1732 break;
1733 case v_mode:
1734 if (dflag)
1735 oappend (names32[reg]);
1736 else
1737 oappend (names16[reg]);
1738 break;
1739 default:
1740 oappend ("<internal disassembler error>");
1741 break;
1742 }
1743 return (0);
1744}
1745
1746static int
1747get32 ()
1748{
1749 int x = 0;
1750
1751 FETCH_DATA (the_info, codep + 4);
1752 x = *codep++ & 0xff;
1753 x |= (*codep++ & 0xff) << 8;
1754 x |= (*codep++ & 0xff) << 16;
1755 x |= (*codep++ & 0xff) << 24;
1756 return (x);
1757}
1758
1759static int
1760get16 ()
1761{
1762 int x = 0;
1763
1764 FETCH_DATA (the_info, codep + 2);
1765 x = *codep++ & 0xff;
1766 x |= (*codep++ & 0xff) << 8;
1767 return (x);
1768}
1769
1770static void
1771set_op (op)
1772 int op;
1773{
1774 op_index[op_ad] = op_ad;
1775 op_address[op_ad] = op;
1776}
1777
be0c8b05
SG
1778static int
1779OP_REG (code, aflag, dflag)
5d0734a7 1780 int code;
be0c8b05
SG
1781 int aflag;
1782 int dflag;
5d0734a7
JK
1783{
1784 char *s;
1785
1786 switch (code)
1787 {
1788 case indir_dx_reg: s = "(%dx)"; break;
1789 case ax_reg: case cx_reg: case dx_reg: case bx_reg:
1790 case sp_reg: case bp_reg: case si_reg: case di_reg:
1791 s = names16[code - ax_reg];
1792 break;
1793 case es_reg: case ss_reg: case cs_reg:
1794 case ds_reg: case fs_reg: case gs_reg:
1795 s = names_seg[code - es_reg];
1796 break;
1797 case al_reg: case ah_reg: case cl_reg: case ch_reg:
1798 case dl_reg: case dh_reg: case bl_reg: case bh_reg:
1799 s = names8[code - al_reg];
1800 break;
1801 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
1802 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
1803 if (dflag)
1804 s = names32[code - eAX_reg];
1805 else
1806 s = names16[code - eAX_reg];
1807 break;
1808 default:
1809 s = "<internal disassembler error>";
1810 break;
1811 }
1812 oappend (s);
1813 return (0);
1814}
1815
be0c8b05
SG
1816static int
1817OP_I (bytemode, aflag, dflag)
5d0734a7 1818 int bytemode;
be0c8b05
SG
1819 int aflag;
1820 int dflag;
5d0734a7
JK
1821{
1822 int op;
1823
1824 switch (bytemode)
1825 {
1826 case b_mode:
1827 FETCH_DATA (the_info, codep + 1);
1828 op = *codep++ & 0xff;
1829 break;
1830 case v_mode:
1831 if (dflag)
1832 op = get32 ();
1833 else
1834 op = get16 ();
1835 break;
1836 case w_mode:
1837 op = get16 ();
1838 break;
1839 default:
1840 oappend ("<internal disassembler error>");
1841 return (0);
1842 }
1843 sprintf (scratchbuf, "$0x%x", op);
1844 oappend (scratchbuf);
1845 return (0);
1846}
1847
be0c8b05
SG
1848static int
1849OP_sI (bytemode, aflag, dflag)
5d0734a7 1850 int bytemode;
be0c8b05
SG
1851 int aflag;
1852 int dflag;
5d0734a7
JK
1853{
1854 int op;
1855
1856 switch (bytemode)
1857 {
1858 case b_mode:
1859 FETCH_DATA (the_info, codep + 1);
1860 op = *(char *)codep++;
1861 break;
1862 case v_mode:
1863 if (dflag)
1864 op = get32 ();
1865 else
1866 op = (short)get16();
1867 break;
1868 case w_mode:
1869 op = (short)get16 ();
1870 break;
1871 default:
1872 oappend ("<internal disassembler error>");
1873 return (0);
1874 }
1875 sprintf (scratchbuf, "$0x%x", op);
1876 oappend (scratchbuf);
1877 return (0);
1878}
1879
be0c8b05
SG
1880static int
1881OP_J (bytemode, aflag, dflag)
5d0734a7 1882 int bytemode;
be0c8b05
SG
1883 int aflag;
1884 int dflag;
5d0734a7
JK
1885{
1886 int disp;
1887 int mask = -1;
1888
1889 switch (bytemode)
1890 {
1891 case b_mode:
1892 FETCH_DATA (the_info, codep + 1);
1893 disp = *(char *)codep++;
1894 break;
1895 case v_mode:
1896 if (dflag)
1897 disp = get32 ();
1898 else
1899 {
1900 disp = (short)get16 ();
1901 /* for some reason, a data16 prefix on a jump instruction
1902 means that the pc is masked to 16 bits after the
1903 displacement is added! */
1904 mask = 0xffff;
1905 }
1906 break;
1907 default:
1908 oappend ("<internal disassembler error>");
1909 return (0);
1910 }
1911 disp = (start_pc + codep - start_codep + disp) & mask;
1912 set_op (disp);
1913 sprintf (scratchbuf, "0x%x", disp);
1914 oappend (scratchbuf);
1915 return (0);
1916}
1917
1918/* ARGSUSED */
be0c8b05
SG
1919static int
1920OP_SEG (dummy, aflag, dflag)
5d0734a7 1921 int dummy;
be0c8b05
SG
1922 int aflag;
1923 int dflag;
5d0734a7
JK
1924{
1925 static char *sreg[] = {
1926 "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
1927 };
1928
1929 oappend (sreg[reg]);
1930 return (0);
1931}
1932
be0c8b05
SG
1933static int
1934OP_DIR (size, aflag, dflag)
5d0734a7 1935 int size;
be0c8b05
SG
1936 int aflag;
1937 int dflag;
5d0734a7
JK
1938{
1939 int seg, offset;
1940
1941 switch (size)
1942 {
1943 case lptr:
1944 if (aflag)
1945 {
1946 offset = get32 ();
1947 seg = get16 ();
1948 }
1949 else
1950 {
1951 offset = get16 ();
1952 seg = get16 ();
1953 }
1954 sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
1955 oappend (scratchbuf);
1956 break;
1957 case v_mode:
1958 if (aflag)
1959 offset = get32 ();
1960 else
1961 offset = (short)get16 ();
1962
1963 offset = start_pc + codep - start_codep + offset;
1964 set_op (offset);
1965 sprintf (scratchbuf, "0x%x", offset);
1966 oappend (scratchbuf);
1967 break;
1968 default:
1969 oappend ("<internal disassembler error>");
1970 break;
1971 }
1972 return (0);
1973}
1974
1975/* ARGSUSED */
be0c8b05
SG
1976static int
1977OP_OFF (bytemode, aflag, dflag)
5d0734a7 1978 int bytemode;
be0c8b05
SG
1979 int aflag;
1980 int dflag;
5d0734a7
JK
1981{
1982 int off;
be0c8b05
SG
1983
1984 append_prefix ();
1985
5d0734a7
JK
1986 if (aflag)
1987 off = get32 ();
1988 else
1989 off = get16 ();
1990
1991 sprintf (scratchbuf, "0x%x", off);
1992 oappend (scratchbuf);
1993 return (0);
1994}
1995
1996/* ARGSUSED */
be0c8b05
SG
1997static int
1998OP_ESDI (dummy, aflag, dflag)
1999 int dummy;
2000 int aflag;
2001 int dflag;
5d0734a7
JK
2002{
2003 oappend ("%es:(");
2004 oappend (aflag ? "%edi" : "%di");
2005 oappend (")");
2006 return (0);
2007}
2008
2009/* ARGSUSED */
be0c8b05
SG
2010static int
2011OP_DSSI (dummy, aflag, dflag)
2012 int dummy;
2013 int aflag;
2014 int dflag;
5d0734a7
JK
2015{
2016 oappend ("%ds:(");
2017 oappend (aflag ? "%esi" : "%si");
2018 oappend (")");
2019 return (0);
2020}
2021
2022/* ARGSUSED */
be0c8b05
SG
2023static int
2024OP_ONE (dummy, aflag, dflag)
2025 int dummy;
2026 int aflag;
2027 int dflag;
5d0734a7
JK
2028{
2029 oappend ("1");
2030 return (0);
2031}
2032
2033/* ARGSUSED */
be0c8b05
SG
2034static int
2035OP_C (dummy, aflag, dflag)
2036 int dummy;
2037 int aflag;
2038 int dflag;
5d0734a7
JK
2039{
2040 codep++; /* skip mod/rm */
2041 sprintf (scratchbuf, "%%cr%d", reg);
2042 oappend (scratchbuf);
2043 return (0);
2044}
2045
2046/* ARGSUSED */
be0c8b05
SG
2047static int
2048OP_D (dummy, aflag, dflag)
2049 int dummy;
2050 int aflag;
2051 int dflag;
5d0734a7
JK
2052{
2053 codep++; /* skip mod/rm */
2054 sprintf (scratchbuf, "%%db%d", reg);
2055 oappend (scratchbuf);
2056 return (0);
2057}
2058
2059/* ARGSUSED */
be0c8b05
SG
2060static int
2061OP_T (dummy, aflag, dflag)
5d0734a7 2062 int dummy;
be0c8b05
SG
2063 int aflag;
2064 int dflag;
5d0734a7
JK
2065{
2066 codep++; /* skip mod/rm */
2067 sprintf (scratchbuf, "%%tr%d", reg);
2068 oappend (scratchbuf);
2069 return (0);
2070}
2071
be0c8b05
SG
2072static int
2073OP_rm (bytemode, aflag, dflag)
5d0734a7 2074 int bytemode;
be0c8b05
SG
2075 int aflag;
2076 int dflag;
5d0734a7
JK
2077{
2078 switch (bytemode)
2079 {
2080 case d_mode:
2081 oappend (names32[rm]);
2082 break;
2083 case w_mode:
2084 oappend (names16[rm]);
2085 break;
2086 }
2087 return (0);
2088}
This page took 0.276343 seconds and 4 git commands to generate.