root / i386-dis.c @ b6d78bfa
History | View | Annotate | Download (44.7 kB)
1 |
/* 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 |
|
5 |
This file is part of GDB.
|
6 |
|
7 |
This program is free software; you can redistribute it and/or modify
|
8 |
it under the terms of the GNU General Public License as published by
|
9 |
the Free Software Foundation; either version 2 of the License, or
|
10 |
(at your option) any later version.
|
11 |
|
12 |
This program is distributed in the hope that it will be useful,
|
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15 |
GNU General Public License for more details.
|
16 |
|
17 |
You should have received a copy of the GNU General Public License
|
18 |
along with this program; if not, write to the Free Software
|
19 |
Foundation, 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 |
|
36 |
#include <stdlib.h> |
37 |
#include <setjmp.h> |
38 |
|
39 |
#include "dis-asm.h" |
40 |
|
41 |
#define MAXLEN 20 |
42 |
|
43 |
static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *)); |
44 |
|
45 |
struct 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 |
|
61 |
static int |
62 |
fetch_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 |
|
151 |
typedef int (*op_rtn) PARAMS ((int bytemode, int aflag, int dflag)); |
152 |
|
153 |
static int OP_E PARAMS ((int, int, int)); |
154 |
static int OP_G PARAMS ((int, int, int)); |
155 |
static int OP_I PARAMS ((int, int, int)); |
156 |
static int OP_indirE PARAMS ((int, int, int)); |
157 |
static int OP_sI PARAMS ((int, int, int)); |
158 |
static int OP_REG PARAMS ((int, int, int)); |
159 |
static int OP_J PARAMS ((int, int, int)); |
160 |
static int OP_DIR PARAMS ((int, int, int)); |
161 |
static int OP_OFF PARAMS ((int, int, int)); |
162 |
static int OP_ESDI PARAMS ((int, int, int)); |
163 |
static int OP_DSSI PARAMS ((int, int, int)); |
164 |
static int OP_SEG PARAMS ((int, int, int)); |
165 |
static int OP_C PARAMS ((int, int, int)); |
166 |
static int OP_D PARAMS ((int, int, int)); |
167 |
static int OP_T PARAMS ((int, int, int)); |
168 |
static int OP_rm PARAMS ((int, int, int)); |
169 |
static int OP_ST PARAMS ((int, int, int)); |
170 |
static int OP_STi PARAMS ((int, int, int)); |
171 |
#if 0
|
172 |
static int OP_ONE PARAMS ((int, int, int));
|
173 |
#endif
|
174 |
static int OP_MMX PARAMS ((int, int, int)); |
175 |
static int OP_EM PARAMS ((int, int, int)); |
176 |
static int OP_MS PARAMS ((int, int, int)); |
177 |
|
178 |
static void append_prefix PARAMS ((void)); |
179 |
static void set_op PARAMS ((int op)); |
180 |
static void putop PARAMS ((char *template, int aflag, int dflag)); |
181 |
static void dofloat PARAMS ((int aflag, int dflag)); |
182 |
static int get16 PARAMS ((void)); |
183 |
static int get32 PARAMS ((void)); |
184 |
static 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 |
|
252 |
struct 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 |
|
262 |
static 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 |
|
553 |
static 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 |
|
779 |
static 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 |
|
798 |
static 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 |
|
817 |
static char obuf[100]; |
818 |
static char *obufp; |
819 |
static char scratchbuf[100]; |
820 |
static unsigned char *start_codep; |
821 |
static unsigned char *codep; |
822 |
static disassemble_info *the_info;
|
823 |
static int mod; |
824 |
static int rm; |
825 |
static int reg; |
826 |
static void oappend PARAMS ((char *s)); |
827 |
|
828 |
static char *names32[]={ |
829 |
"%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi", |
830 |
}; |
831 |
static char *names16[] = { |
832 |
"%ax","%cx","%dx","%bx","%sp","%bp","%si","%di", |
833 |
}; |
834 |
static char *names8[] = { |
835 |
"%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh", |
836 |
}; |
837 |
static char *names_seg[] = { |
838 |
"%es","%cs","%ss","%ds","%fs","%gs","%?","%?", |
839 |
}; |
840 |
static char *index16[] = { |
841 |
"bx+si","bx+di","bp+si","bp+di","si","di","bp","bx" |
842 |
}; |
843 |
|
844 |
static 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 |
|
1080 |
static int prefixes; |
1081 |
|
1082 |
static void |
1083 |
ckprefix () |
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 |
|
1134 |
static char op1out[100], op2out[100], op3out[100]; |
1135 |
static int op_address[3], op_ad, op_index[3]; |
1136 |
static 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 |
|
1148 |
int print_insn_x86 PARAMS ((bfd_vma pc, disassemble_info *info, int aflag, |
1149 |
int dflag));
|
1150 |
int
|
1151 |
print_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 |
|
1163 |
int
|
1164 |
print_insn_x86 (pc, info, aflag, dflag) |
1165 |
bfd_vma pc; |
1166 |
disassemble_info *info; |
1167 |
int volatile aflag; |
1168 |
int volatile dflag; |
1169 |
{ |
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 |
|
1344 |
static 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 |
|
1432 |
static 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 |
|
1524 |
static 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 |
|
1572 |
static void |
1573 |
dofloat (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 */
|
1614 |
static int |
1615 |
OP_ST (ignore, aflag, dflag) |
1616 |
int ignore;
|
1617 |
int aflag;
|
1618 |
int dflag;
|
1619 |
{ |
1620 |
oappend ("%st");
|
1621 |
return (0); |
1622 |
} |
1623 |
|
1624 |
/* ARGSUSED */
|
1625 |
static int |
1626 |
OP_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 */
|
1638 |
static void |
1639 |
putop (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 |
|
1680 |
static void |
1681 |
oappend (s) |
1682 |
char *s;
|
1683 |
{ |
1684 |
strcpy (obufp, s); |
1685 |
obufp += strlen (s); |
1686 |
*obufp = 0;
|
1687 |
} |
1688 |
|
1689 |
static void |
1690 |
append_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 |
|
1706 |
static int |
1707 |
OP_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 |
|
1716 |
static int |
1717 |
OP_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 |
|
1860 |
static int |
1861 |
OP_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 |
|
1890 |
static int |
1891 |
get32 () |
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 |
|
1903 |
static int |
1904 |
get16 () |
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 |
|
1914 |
static void |
1915 |
set_op (op) |
1916 |
int op;
|
1917 |
{ |
1918 |
op_index[op_ad] = op_ad; |
1919 |
op_address[op_ad] = op; |
1920 |
} |
1921 |
|
1922 |
static int |
1923 |
OP_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 |
|
1960 |
static int |
1961 |
OP_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 |
|
1992 |
static int |
1993 |
OP_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 |
|
2032 |
static int |
2033 |
OP_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 */
|
2075 |
static int |
2076 |
OP_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 |
|
2089 |
static int |
2090 |
OP_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 */
|
2136 |
static int |
2137 |
OP_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 */
|
2157 |
static int |
2158 |
OP_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 */
|
2170 |
static int |
2171 |
OP_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 */
|
2195 |
static int
|
2196 |
OP_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 */
|
2208 |
static int |
2209 |
OP_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 */
|
2221 |
static int |
2222 |
OP_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 */
|
2234 |
static int |
2235 |
OP_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 |
|
2246 |
static int |
2247 |
OP_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 |
|
2264 |
static int |
2265 |
OP_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 |
|
2275 |
static int |
2276 |
OP_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 |
|
2290 |
static int |
2291 |
OP_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 |
} |