]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
6601e61a | 4 | * @APPLE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
6601e61a A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
8f6c56a5 | 11 | * |
6601e61a A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
8f6c56a5 A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
6601e61a A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
8f6c56a5 | 19 | * |
6601e61a | 20 | * @APPLE_LICENSE_HEADER_END@ |
1c79356b A |
21 | */ |
22 | /* | |
23 | * @OSF_COPYRIGHT@ | |
24 | */ | |
25 | /* | |
26 | * HISTORY | |
27 | * | |
28 | * Revision 1.1.1.1 1998/09/22 21:05:36 wsanchez | |
29 | * Import of Mac OS X kernel (~semeria) | |
30 | * | |
31 | * Revision 1.1.1.1 1998/03/07 02:25:37 wsanchez | |
32 | * Import of OSF Mach kernel (~mburg) | |
33 | * | |
34 | * Revision 1.2.8.3 1996/07/31 09:43:35 paire | |
35 | * Merged with nmk20b7_shared (1.2.11.1) | |
36 | * [96/06/10 paire] | |
37 | * | |
38 | * Revision 1.2.11.1 1996/05/14 13:49:36 paire | |
39 | * Added support for new cmpxchg8b, cpuid, rdtsc, rdwmr, rsm and wrmsr | |
40 | * Pentium instructions | |
41 | * [95/11/23 paire] | |
42 | * | |
43 | * Revision 1.2.8.2 1994/09/23 01:50:45 ezf | |
44 | * change marker to not FREE | |
45 | * [1994/09/22 21:21:17 ezf] | |
46 | * | |
47 | * Revision 1.2.8.1 1994/09/16 15:26:28 emcmanus | |
48 | * Only skip over GAS-inserted NOPs after branches if they are really | |
49 | * NOPs; this depends at least on assembler options. | |
50 | * [1994/09/16 15:26:03 emcmanus] | |
51 | * | |
52 | * Revision 1.2.6.3 1994/02/19 15:40:34 bolinger | |
53 | * For load/store counting, mark all varieties of "call" as writing | |
54 | * memory. | |
55 | * [1994/02/15 20:25:18 bolinger] | |
56 | * | |
57 | * Revision 1.2.6.2 1994/02/14 21:46:49 dwm | |
58 | * Warning repair | |
59 | * [1994/02/14 21:46:14 dwm] | |
60 | * | |
61 | * Revision 1.2.6.1 1994/02/12 23:26:05 bolinger | |
62 | * Implement load/store counting for ddb "until" command. | |
63 | * [1994/02/12 03:34:55 bolinger] | |
64 | * | |
65 | * Revision 1.2.2.3 1993/08/09 19:39:21 dswartz | |
66 | * Add ANSI prototypes - CR#9523 | |
67 | * [1993/08/06 17:44:13 dswartz] | |
68 | * | |
69 | * Revision 1.2.2.2 1993/06/09 02:27:29 gm | |
70 | * Added to OSF/1 R1.3 from NMK15.0. | |
71 | * [1993/06/02 21:03:54 jeffc] | |
72 | * | |
73 | * Revision 1.2 1993/04/19 16:12:57 devrcs | |
74 | * Print file names and lineno on branch instructions. | |
75 | * [barbou@gr.osf.org] | |
76 | * [92/12/03 bernadat] | |
77 | * | |
78 | * Revision 1.1 1992/09/30 02:02:19 robert | |
79 | * Initial revision | |
80 | * | |
81 | * $EndLog$ | |
82 | */ | |
83 | /* CMU_HIST */ | |
84 | /* | |
85 | * Revision 2.5.3.1 92/03/03 16:14:27 jeffreyh | |
86 | * Pick up changes from TRUNK | |
87 | * [92/02/26 11:05:06 jeffreyh] | |
88 | * | |
89 | * Revision 2.6 92/01/03 20:05:00 dbg | |
90 | * Add a switch to disassemble 16-bit code. | |
91 | * Fix spelling of 'lods' opcodes. | |
92 | * [91/10/30 dbg] | |
93 | * | |
94 | * Revision 2.5 91/10/09 16:05:58 af | |
95 | * Supported disassemble of non current task by passing task parameter. | |
96 | * [91/08/29 tak] | |
97 | * | |
98 | * Revision 2.4 91/05/14 16:05:04 mrt | |
99 | * Correcting copyright | |
100 | * | |
101 | * Revision 2.3 91/02/05 17:11:03 mrt | |
102 | * Changed to new Mach copyright | |
103 | * [91/02/01 17:31:03 mrt] | |
104 | * | |
105 | * Revision 2.2 90/08/27 21:55:56 dbg | |
106 | * Fix register operand for move to/from control/test/debug | |
107 | * register instructions. Add i486 instructions. | |
108 | * [90/08/27 dbg] | |
109 | * | |
110 | * Import db_sym.h. Print instruction displacements in | |
111 | * current radix (signed). Change calling sequence of | |
112 | * db_disasm. | |
113 | * [90/08/21 dbg] | |
114 | * Fix includes. | |
115 | * [90/08/08 dbg] | |
116 | * Created. | |
117 | * [90/07/25 dbg] | |
118 | * | |
119 | */ | |
120 | /* CMU_ENDHIST */ | |
121 | /* | |
122 | * Mach Operating System | |
123 | * Copyright (c) 1991,1990 Carnegie Mellon University | |
124 | * All Rights Reserved. | |
125 | * | |
126 | * Permission to use, copy, modify and distribute this software and its | |
127 | * documentation is hereby granted, provided that both the copyright | |
128 | * notice and this permission notice appear in all copies of the | |
129 | * software, derivative works or modified versions, and any portions | |
130 | * thereof, and that both notices appear in supporting documentation. | |
131 | * | |
132 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
133 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
134 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
135 | * | |
136 | * Carnegie Mellon requests users of this software to return to | |
137 | * | |
138 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
139 | * School of Computer Science | |
140 | * Carnegie Mellon University | |
141 | * Pittsburgh PA 15213-3890 | |
142 | * | |
143 | * any improvements or extensions that they make and grant Carnegie Mellon | |
144 | * the rights to redistribute these changes. | |
145 | */ | |
146 | /* | |
147 | */ | |
148 | ||
149 | /* | |
150 | * Instruction disassembler. | |
151 | */ | |
152 | ||
153 | #include <mach/boolean.h> | |
154 | #include <machine/db_machdep.h> | |
155 | ||
156 | #include <ddb/db_access.h> | |
157 | #include <ddb/db_sym.h> | |
158 | #include <ddb/db_output.h> | |
159 | ||
160 | #include <kern/task.h> | |
161 | #include <kern/misc_protos.h> | |
162 | ||
163 | struct i_addr { | |
164 | int is_reg; /* if reg, reg number is in 'disp' */ | |
165 | int disp; | |
166 | char * base; | |
167 | char * index; | |
168 | int ss; | |
169 | }; | |
170 | ||
171 | /* Forward */ | |
172 | ||
173 | extern db_addr_t db_read_address( | |
174 | db_addr_t loc, | |
175 | int short_addr, | |
176 | int regmodrm, | |
177 | struct i_addr * addrp, | |
178 | task_t task); | |
179 | extern void db_print_address( | |
180 | char * seg, | |
181 | int size, | |
182 | struct i_addr *addrp, | |
183 | task_t task); | |
184 | extern db_addr_t db_disasm_esc( | |
185 | db_addr_t loc, | |
186 | int inst, | |
187 | int short_addr, | |
188 | int size, | |
189 | char * seg, | |
190 | task_t task); | |
191 | ||
192 | /* | |
193 | * Switch to disassemble 16-bit code. | |
194 | */ | |
195 | boolean_t db_disasm_16 = FALSE; | |
196 | ||
197 | /* | |
198 | * Size attributes | |
199 | */ | |
200 | #define BYTE 0 | |
201 | #define WORD 1 | |
202 | #define LONG 2 | |
203 | #define QUAD 3 | |
204 | #define SNGL 4 | |
205 | #define DBLR 5 | |
206 | #define EXTR 6 | |
207 | #define SDEP 7 | |
208 | #define NONE 8 | |
209 | ||
210 | /* | |
211 | * Addressing modes | |
212 | */ | |
213 | #define E 1 /* general effective address */ | |
214 | #define Eind 2 /* indirect address (jump, call) */ | |
215 | #define Ew 3 /* address, word size */ | |
216 | #define Eb 4 /* address, byte size */ | |
217 | #define R 5 /* register, in 'reg' field */ | |
218 | #define Rw 6 /* word register, in 'reg' field */ | |
219 | #define Ri 7 /* register in instruction */ | |
220 | #define S 8 /* segment reg, in 'reg' field */ | |
221 | #define Si 9 /* segment reg, in instruction */ | |
222 | #define A 10 /* accumulator */ | |
223 | #define BX 11 /* (bx) */ | |
224 | #define CL 12 /* cl, for shifts */ | |
225 | #define DX 13 /* dx, for IO */ | |
226 | #define SI 14 /* si */ | |
227 | #define DI 15 /* di */ | |
228 | #define CR 16 /* control register */ | |
229 | #define DR 17 /* debug register */ | |
230 | #define TR 18 /* test register */ | |
231 | #define I 19 /* immediate, unsigned */ | |
232 | #define Is 20 /* immediate, signed */ | |
233 | #define Ib 21 /* byte immediate, unsigned */ | |
234 | #define Ibs 22 /* byte immediate, signed */ | |
235 | #define Iw 23 /* word immediate, unsigned */ | |
236 | #define Il 24 /* long immediate */ | |
237 | #define O 25 /* direct address */ | |
238 | #define Db 26 /* byte displacement from EIP */ | |
239 | #define Dl 27 /* long displacement from EIP */ | |
240 | #define o1 28 /* constant 1 */ | |
241 | #define o3 29 /* constant 3 */ | |
242 | #define OS 30 /* immediate offset/segment */ | |
243 | #define ST 31 /* FP stack top */ | |
244 | #define STI 32 /* FP stack */ | |
245 | #define X 33 /* extended FP op */ | |
246 | #define XA 34 /* for 'fstcw %ax' */ | |
247 | ||
248 | struct inst { | |
249 | char * i_name; /* name */ | |
250 | short i_has_modrm; /* has regmodrm byte */ | |
251 | short i_size; /* operand size */ | |
252 | int i_mode; /* addressing modes */ | |
253 | char * i_extra; /* pointer to extra opcode table */ | |
254 | }; | |
255 | ||
256 | #define op1(x) (x) | |
257 | #define op2(x,y) ((x)|((y)<<8)) | |
258 | #define op3(x,y,z) ((x)|((y)<<8)|((z)<<16)) | |
259 | ||
260 | struct finst { | |
261 | char * f_name; /* name for memory instruction */ | |
262 | int f_size; /* size for memory instruction */ | |
263 | int f_rrmode; /* mode for rr instruction */ | |
264 | char * f_rrname; /* name for rr instruction | |
265 | (or pointer to table) */ | |
266 | }; | |
267 | ||
268 | char * db_Grp6[] = { | |
269 | "sldt", | |
270 | "str", | |
271 | "lldt", | |
272 | "ltr", | |
273 | "verr", | |
274 | "verw", | |
275 | "", | |
276 | "" | |
277 | }; | |
278 | ||
279 | char * db_Grp7[] = { | |
280 | "sgdt", | |
281 | "sidt", | |
282 | "lgdt", | |
283 | "lidt", | |
284 | "smsw", | |
285 | "", | |
286 | "lmsw", | |
287 | "invlpg" | |
288 | }; | |
289 | ||
290 | char * db_Grp8[] = { | |
291 | "", | |
292 | "", | |
293 | "", | |
294 | "", | |
295 | "bt", | |
296 | "bts", | |
297 | "btr", | |
298 | "btc" | |
299 | }; | |
300 | ||
301 | struct inst db_inst_0f0x[] = { | |
302 | /*00*/ { "", TRUE, NONE, op1(Ew), (char *)db_Grp6 }, | |
303 | /*01*/ { "", TRUE, NONE, op1(Ew), (char *)db_Grp7 }, | |
304 | /*02*/ { "lar", TRUE, LONG, op2(E,R), 0 }, | |
305 | /*03*/ { "lsl", TRUE, LONG, op2(E,R), 0 }, | |
306 | /*04*/ { "", FALSE, NONE, 0, 0 }, | |
307 | /*05*/ { "", FALSE, NONE, 0, 0 }, | |
308 | /*06*/ { "clts", FALSE, NONE, 0, 0 }, | |
309 | /*07*/ { "", FALSE, NONE, 0, 0 }, | |
310 | ||
311 | /*08*/ { "invd", FALSE, NONE, 0, 0 }, | |
312 | /*09*/ { "wbinvd",FALSE, NONE, 0, 0 }, | |
313 | /*0a*/ { "", FALSE, NONE, 0, 0 }, | |
314 | /*0b*/ { "", FALSE, NONE, 0, 0 }, | |
315 | /*0c*/ { "", FALSE, NONE, 0, 0 }, | |
316 | /*0d*/ { "", FALSE, NONE, 0, 0 }, | |
317 | /*0e*/ { "", FALSE, NONE, 0, 0 }, | |
318 | /*0f*/ { "", FALSE, NONE, 0, 0 }, | |
319 | }; | |
320 | ||
321 | struct inst db_inst_0f2x[] = { | |
322 | /*20*/ { "mov", TRUE, LONG, op2(CR,E), 0 }, /* use E for reg */ | |
323 | /*21*/ { "mov", TRUE, LONG, op2(DR,E), 0 }, /* since mod == 11 */ | |
324 | /*22*/ { "mov", TRUE, LONG, op2(E,CR), 0 }, | |
325 | /*23*/ { "mov", TRUE, LONG, op2(E,DR), 0 }, | |
326 | /*24*/ { "mov", TRUE, LONG, op2(TR,E), 0 }, | |
327 | /*25*/ { "", FALSE, NONE, 0, 0 }, | |
328 | /*26*/ { "mov", TRUE, LONG, op2(E,TR), 0 }, | |
329 | /*27*/ { "", FALSE, NONE, 0, 0 }, | |
330 | ||
331 | /*28*/ { "", FALSE, NONE, 0, 0 }, | |
332 | /*29*/ { "", FALSE, NONE, 0, 0 }, | |
333 | /*2a*/ { "", FALSE, NONE, 0, 0 }, | |
334 | /*2b*/ { "", FALSE, NONE, 0, 0 }, | |
335 | /*2c*/ { "", FALSE, NONE, 0, 0 }, | |
336 | /*2d*/ { "", FALSE, NONE, 0, 0 }, | |
337 | /*2e*/ { "", FALSE, NONE, 0, 0 }, | |
338 | /*2f*/ { "", FALSE, NONE, 0, 0 }, | |
339 | }; | |
340 | struct inst db_inst_0f3x[] = { | |
341 | /*30*/ { "rdtsc", FALSE, NONE, 0, 0 }, | |
342 | /*31*/ { "rdmsr", FALSE, NONE, 0, 0 }, | |
343 | /*32*/ { "wrmsr", FALSE, NONE, 0, 0 }, | |
344 | /*33*/ { "", FALSE, NONE, 0, 0 }, | |
345 | /*34*/ { "", FALSE, NONE, 0, 0 }, | |
346 | /*35*/ { "", FALSE, NONE, 0, 0 }, | |
347 | /*36*/ { "", FALSE, NONE, 0, 0 }, | |
348 | /*37*/ { "", FALSE, NONE, 0, 0 }, | |
349 | ||
350 | /*38*/ { "", FALSE, NONE, 0, 0 }, | |
351 | /*39*/ { "", FALSE, NONE, 0, 0 }, | |
352 | /*3a*/ { "", FALSE, NONE, 0, 0 }, | |
353 | /*3b*/ { "", FALSE, NONE, 0, 0 }, | |
354 | /*3c*/ { "", FALSE, NONE, 0, 0 }, | |
355 | /*3d*/ { "", FALSE, NONE, 0, 0 }, | |
356 | /*3e*/ { "", FALSE, NONE, 0, 0 }, | |
357 | /*3f*/ { "", FALSE, NONE, 0, 0 }, | |
358 | }; | |
359 | ||
360 | struct inst db_inst_0f8x[] = { | |
361 | /*80*/ { "jo", FALSE, NONE, op1(Dl), 0 }, | |
362 | /*81*/ { "jno", FALSE, NONE, op1(Dl), 0 }, | |
363 | /*82*/ { "jb", FALSE, NONE, op1(Dl), 0 }, | |
364 | /*83*/ { "jnb", FALSE, NONE, op1(Dl), 0 }, | |
365 | /*84*/ { "jz", FALSE, NONE, op1(Dl), 0 }, | |
366 | /*85*/ { "jnz", FALSE, NONE, op1(Dl), 0 }, | |
367 | /*86*/ { "jbe", FALSE, NONE, op1(Dl), 0 }, | |
368 | /*87*/ { "jnbe", FALSE, NONE, op1(Dl), 0 }, | |
369 | ||
370 | /*88*/ { "js", FALSE, NONE, op1(Dl), 0 }, | |
371 | /*89*/ { "jns", FALSE, NONE, op1(Dl), 0 }, | |
372 | /*8a*/ { "jp", FALSE, NONE, op1(Dl), 0 }, | |
373 | /*8b*/ { "jnp", FALSE, NONE, op1(Dl), 0 }, | |
374 | /*8c*/ { "jl", FALSE, NONE, op1(Dl), 0 }, | |
375 | /*8d*/ { "jnl", FALSE, NONE, op1(Dl), 0 }, | |
376 | /*8e*/ { "jle", FALSE, NONE, op1(Dl), 0 }, | |
377 | /*8f*/ { "jnle", FALSE, NONE, op1(Dl), 0 }, | |
378 | }; | |
379 | ||
380 | struct inst db_inst_0f9x[] = { | |
381 | /*90*/ { "seto", TRUE, NONE, op1(Eb), 0 }, | |
382 | /*91*/ { "setno", TRUE, NONE, op1(Eb), 0 }, | |
383 | /*92*/ { "setb", TRUE, NONE, op1(Eb), 0 }, | |
384 | /*93*/ { "setnb", TRUE, NONE, op1(Eb), 0 }, | |
385 | /*94*/ { "setz", TRUE, NONE, op1(Eb), 0 }, | |
386 | /*95*/ { "setnz", TRUE, NONE, op1(Eb), 0 }, | |
387 | /*96*/ { "setbe", TRUE, NONE, op1(Eb), 0 }, | |
388 | /*97*/ { "setnbe",TRUE, NONE, op1(Eb), 0 }, | |
389 | ||
390 | /*98*/ { "sets", TRUE, NONE, op1(Eb), 0 }, | |
391 | /*99*/ { "setns", TRUE, NONE, op1(Eb), 0 }, | |
392 | /*9a*/ { "setp", TRUE, NONE, op1(Eb), 0 }, | |
393 | /*9b*/ { "setnp", TRUE, NONE, op1(Eb), 0 }, | |
394 | /*9c*/ { "setl", TRUE, NONE, op1(Eb), 0 }, | |
395 | /*9d*/ { "setnl", TRUE, NONE, op1(Eb), 0 }, | |
396 | /*9e*/ { "setle", TRUE, NONE, op1(Eb), 0 }, | |
397 | /*9f*/ { "setnle",TRUE, NONE, op1(Eb), 0 }, | |
398 | }; | |
399 | ||
400 | struct inst db_inst_0fax[] = { | |
401 | /*a0*/ { "push", FALSE, NONE, op1(Si), 0 }, | |
402 | /*a1*/ { "pop", FALSE, NONE, op1(Si), 0 }, | |
403 | /*a2*/ { "cpuid", FALSE, NONE, 0, 0 }, | |
404 | /*a3*/ { "bt", TRUE, LONG, op2(E,R), 0 }, | |
405 | /*a4*/ { "shld", TRUE, LONG, op3(Ib,E,R), 0 }, | |
406 | /*a5*/ { "shld", TRUE, LONG, op3(CL,E,R), 0 }, | |
407 | /*a6*/ { "", FALSE, NONE, 0, 0 }, | |
408 | /*a7*/ { "", FALSE, NONE, 0, 0 }, | |
409 | ||
410 | /*a8*/ { "push", FALSE, NONE, op1(Si), 0 }, | |
411 | /*a9*/ { "pop", FALSE, NONE, op1(Si), 0 }, | |
412 | /*aa*/ { "rsm", FALSE, NONE, 0, 0 }, | |
413 | /*ab*/ { "bts", TRUE, LONG, op2(E,R), 0 }, | |
414 | /*ac*/ { "shrd", TRUE, LONG, op3(Ib,E,R), 0 }, | |
415 | /*ad*/ { "shrd", TRUE, LONG, op3(CL,E,R), 0 }, | |
416 | /*a6*/ { "", FALSE, NONE, 0, 0 }, | |
417 | /*a7*/ { "imul", TRUE, LONG, op2(E,R), 0 }, | |
418 | }; | |
419 | ||
420 | struct inst db_inst_0fbx[] = { | |
421 | /*b0*/ { "", FALSE, NONE, 0, 0 }, | |
422 | /*b1*/ { "", FALSE, NONE, 0, 0 }, | |
423 | /*b2*/ { "lss", TRUE, LONG, op2(E, R), 0 }, | |
424 | /*b3*/ { "bts", TRUE, LONG, op2(R, E), 0 }, | |
425 | /*b4*/ { "lfs", TRUE, LONG, op2(E, R), 0 }, | |
426 | /*b5*/ { "lgs", TRUE, LONG, op2(E, R), 0 }, | |
427 | /*b6*/ { "movzb", TRUE, LONG, op2(E, R), 0 }, | |
428 | /*b7*/ { "movzw", TRUE, LONG, op2(E, R), 0 }, | |
429 | ||
430 | /*b8*/ { "", FALSE, NONE, 0, 0 }, | |
431 | /*b9*/ { "", FALSE, NONE, 0, 0 }, | |
432 | /*ba*/ { "", TRUE, LONG, op2(Is, E), (char *)db_Grp8 }, | |
433 | /*bb*/ { "btc", TRUE, LONG, op2(R, E), 0 }, | |
434 | /*bc*/ { "bsf", TRUE, LONG, op2(E, R), 0 }, | |
435 | /*bd*/ { "bsr", TRUE, LONG, op2(E, R), 0 }, | |
436 | /*be*/ { "movsb", TRUE, LONG, op2(E, R), 0 }, | |
437 | /*bf*/ { "movsw", TRUE, LONG, op2(E, R), 0 }, | |
438 | }; | |
439 | ||
440 | struct inst db_inst_0fcx[] = { | |
441 | /*c0*/ { "xadd", TRUE, BYTE, op2(R, E), 0 }, | |
442 | /*c1*/ { "xadd", TRUE, LONG, op2(R, E), 0 }, | |
443 | /*c2*/ { "", FALSE, NONE, 0, 0 }, | |
444 | /*c3*/ { "", FALSE, NONE, 0, 0 }, | |
445 | /*c4*/ { "", FALSE, NONE, 0, 0 }, | |
446 | /*c5*/ { "", FALSE, NONE, 0, 0 }, | |
447 | /*c6*/ { "", FALSE, NONE, 0, 0 }, | |
448 | /*c7*/ { "cmpxchg8b", FALSE, NONE, op1(E), 0 }, | |
449 | /*c8*/ { "bswap", FALSE, LONG, op1(Ri), 0 }, | |
450 | /*c9*/ { "bswap", FALSE, LONG, op1(Ri), 0 }, | |
451 | /*ca*/ { "bswap", FALSE, LONG, op1(Ri), 0 }, | |
452 | /*cb*/ { "bswap", FALSE, LONG, op1(Ri), 0 }, | |
453 | /*cc*/ { "bswap", FALSE, LONG, op1(Ri), 0 }, | |
454 | /*cd*/ { "bswap", FALSE, LONG, op1(Ri), 0 }, | |
455 | /*ce*/ { "bswap", FALSE, LONG, op1(Ri), 0 }, | |
456 | /*cf*/ { "bswap", FALSE, LONG, op1(Ri), 0 }, | |
457 | }; | |
458 | ||
459 | struct inst db_inst_0fdx[] = { | |
460 | /*c0*/ { "cmpxchg",TRUE, BYTE, op2(R, E), 0 }, | |
461 | /*c1*/ { "cmpxchg",TRUE, LONG, op2(R, E), 0 }, | |
462 | /*c2*/ { "", FALSE, NONE, 0, 0 }, | |
463 | /*c3*/ { "", FALSE, NONE, 0, 0 }, | |
464 | /*c4*/ { "", FALSE, NONE, 0, 0 }, | |
465 | /*c5*/ { "", FALSE, NONE, 0, 0 }, | |
466 | /*c6*/ { "", FALSE, NONE, 0, 0 }, | |
467 | /*c7*/ { "", FALSE, NONE, 0, 0 }, | |
468 | /*c8*/ { "", FALSE, NONE, 0, 0 }, | |
469 | /*c9*/ { "", FALSE, NONE, 0, 0 }, | |
470 | /*ca*/ { "", FALSE, NONE, 0, 0 }, | |
471 | /*cb*/ { "", FALSE, NONE, 0, 0 }, | |
472 | /*cc*/ { "", FALSE, NONE, 0, 0 }, | |
473 | /*cd*/ { "", FALSE, NONE, 0, 0 }, | |
474 | /*ce*/ { "", FALSE, NONE, 0, 0 }, | |
475 | /*cf*/ { "", FALSE, NONE, 0, 0 }, | |
476 | }; | |
477 | ||
478 | struct inst *db_inst_0f[] = { | |
479 | db_inst_0f0x, | |
480 | 0, | |
481 | db_inst_0f2x, | |
482 | db_inst_0f3x, | |
483 | 0, | |
484 | 0, | |
485 | 0, | |
486 | 0, | |
487 | db_inst_0f8x, | |
488 | db_inst_0f9x, | |
489 | db_inst_0fax, | |
490 | db_inst_0fbx, | |
491 | db_inst_0fcx, | |
492 | db_inst_0fdx, | |
493 | 0, | |
494 | 0 | |
495 | }; | |
496 | ||
497 | char * db_Esc92[] = { | |
498 | "fnop", "", "", "", "", "", "", "" | |
499 | }; | |
500 | char * db_Esc93[] = { | |
501 | "", "", "", "", "", "", "", "" | |
502 | }; | |
503 | char * db_Esc94[] = { | |
504 | "fchs", "fabs", "", "", "ftst", "fxam", "", "" | |
505 | }; | |
506 | char * db_Esc95[] = { | |
507 | "fld1", "fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","" | |
508 | }; | |
509 | char * db_Esc96[] = { | |
510 | "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp", | |
511 | "fincstp" | |
512 | }; | |
513 | char * db_Esc97[] = { | |
514 | "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos" | |
515 | }; | |
516 | ||
517 | char * db_Esca4[] = { | |
518 | "", "fucompp","", "", "", "", "", "" | |
519 | }; | |
520 | ||
521 | char * db_Escb4[] = { | |
522 | "", "", "fnclex","fninit","", "", "", "" | |
523 | }; | |
524 | ||
525 | char * db_Esce3[] = { | |
526 | "", "fcompp","", "", "", "", "", "" | |
527 | }; | |
528 | ||
529 | char * db_Escf4[] = { | |
530 | "fnstsw","", "", "", "", "", "", "" | |
531 | }; | |
532 | ||
533 | struct finst db_Esc8[] = { | |
534 | /*0*/ { "fadd", SNGL, op2(STI,ST), 0 }, | |
535 | /*1*/ { "fmul", SNGL, op2(STI,ST), 0 }, | |
536 | /*2*/ { "fcom", SNGL, op2(STI,ST), 0 }, | |
537 | /*3*/ { "fcomp", SNGL, op2(STI,ST), 0 }, | |
538 | /*4*/ { "fsub", SNGL, op2(STI,ST), 0 }, | |
539 | /*5*/ { "fsubr", SNGL, op2(STI,ST), 0 }, | |
540 | /*6*/ { "fdiv", SNGL, op2(STI,ST), 0 }, | |
541 | /*7*/ { "fdivr", SNGL, op2(STI,ST), 0 }, | |
542 | }; | |
543 | ||
544 | struct finst db_Esc9[] = { | |
545 | /*0*/ { "fld", SNGL, op1(STI), 0 }, | |
546 | /*1*/ { "", NONE, op1(STI), "fxch" }, | |
547 | /*2*/ { "fst", SNGL, op1(X), (char *)db_Esc92 }, | |
548 | /*3*/ { "fstp", SNGL, op1(X), (char *)db_Esc93 }, | |
549 | /*4*/ { "fldenv", NONE, op1(X), (char *)db_Esc94 }, | |
550 | /*5*/ { "fldcw", NONE, op1(X), (char *)db_Esc95 }, | |
551 | /*6*/ { "fnstenv",NONE, op1(X), (char *)db_Esc96 }, | |
552 | /*7*/ { "fnstcw", NONE, op1(X), (char *)db_Esc97 }, | |
553 | }; | |
554 | ||
555 | struct finst db_Esca[] = { | |
556 | /*0*/ { "fiadd", WORD, 0, 0 }, | |
557 | /*1*/ { "fimul", WORD, 0, 0 }, | |
558 | /*2*/ { "ficom", WORD, 0, 0 }, | |
559 | /*3*/ { "ficomp", WORD, 0, 0 }, | |
560 | /*4*/ { "fisub", WORD, op1(X), (char *)db_Esca4 }, | |
561 | /*5*/ { "fisubr", WORD, 0, 0 }, | |
562 | /*6*/ { "fidiv", WORD, 0, 0 }, | |
563 | /*7*/ { "fidivr", WORD, 0, 0 } | |
564 | }; | |
565 | ||
566 | struct finst db_Escb[] = { | |
567 | /*0*/ { "fild", WORD, 0, 0 }, | |
568 | /*1*/ { "", NONE, 0, 0 }, | |
569 | /*2*/ { "fist", WORD, 0, 0 }, | |
570 | /*3*/ { "fistp", WORD, 0, 0 }, | |
571 | /*4*/ { "", WORD, op1(X), (char *)db_Escb4 }, | |
572 | /*5*/ { "fld", EXTR, 0, 0 }, | |
573 | /*6*/ { "", WORD, 0, 0 }, | |
574 | /*7*/ { "fstp", EXTR, 0, 0 }, | |
575 | }; | |
576 | ||
577 | struct finst db_Escc[] = { | |
578 | /*0*/ { "fadd", DBLR, op2(ST,STI), 0 }, | |
579 | /*1*/ { "fmul", DBLR, op2(ST,STI), 0 }, | |
580 | /*2*/ { "fcom", DBLR, op2(ST,STI), 0 }, | |
581 | /*3*/ { "fcomp", DBLR, op2(ST,STI), 0 }, | |
582 | /*4*/ { "fsub", DBLR, op2(ST,STI), "fsubr" }, | |
583 | /*5*/ { "fsubr", DBLR, op2(ST,STI), "fsub" }, | |
584 | /*6*/ { "fdiv", DBLR, op2(ST,STI), "fdivr" }, | |
585 | /*7*/ { "fdivr", DBLR, op2(ST,STI), "fdiv" }, | |
586 | }; | |
587 | ||
588 | struct finst db_Escd[] = { | |
589 | /*0*/ { "fld", DBLR, op1(STI), "ffree" }, | |
590 | /*1*/ { "", NONE, 0, 0 }, | |
591 | /*2*/ { "fst", DBLR, op1(STI), 0 }, | |
592 | /*3*/ { "fstp", DBLR, op1(STI), 0 }, | |
593 | /*4*/ { "frstor", NONE, op1(STI), "fucom" }, | |
594 | /*5*/ { "", NONE, op1(STI), "fucomp" }, | |
595 | /*6*/ { "fnsave", NONE, 0, 0 }, | |
596 | /*7*/ { "fnstsw", NONE, 0, 0 }, | |
597 | }; | |
598 | ||
599 | struct finst db_Esce[] = { | |
600 | /*0*/ { "fiadd", LONG, op2(ST,STI), "faddp" }, | |
601 | /*1*/ { "fimul", LONG, op2(ST,STI), "fmulp" }, | |
602 | /*2*/ { "ficom", LONG, 0, 0 }, | |
603 | /*3*/ { "ficomp", LONG, op1(X), (char *)db_Esce3 }, | |
604 | /*4*/ { "fisub", LONG, op2(ST,STI), "fsubrp" }, | |
605 | /*5*/ { "fisubr", LONG, op2(ST,STI), "fsubp" }, | |
606 | /*6*/ { "fidiv", LONG, op2(ST,STI), "fdivrp" }, | |
607 | /*7*/ { "fidivr", LONG, op2(ST,STI), "fdivp" }, | |
608 | }; | |
609 | ||
610 | struct finst db_Escf[] = { | |
611 | /*0*/ { "fild", LONG, 0, 0 }, | |
612 | /*1*/ { "", LONG, 0, 0 }, | |
613 | /*2*/ { "fist", LONG, 0, 0 }, | |
614 | /*3*/ { "fistp", LONG, 0, 0 }, | |
615 | /*4*/ { "fbld", NONE, op1(XA), (char *)db_Escf4 }, | |
616 | /*5*/ { "fld", QUAD, 0, 0 }, | |
617 | /*6*/ { "fbstp", NONE, 0, 0 }, | |
618 | /*7*/ { "fstp", QUAD, 0, 0 }, | |
619 | }; | |
620 | ||
621 | struct finst *db_Esc_inst[] = { | |
622 | db_Esc8, db_Esc9, db_Esca, db_Escb, | |
623 | db_Escc, db_Escd, db_Esce, db_Escf | |
624 | }; | |
625 | ||
626 | char * db_Grp1[] = { | |
627 | "add", | |
628 | "or", | |
629 | "adc", | |
630 | "sbb", | |
631 | "and", | |
632 | "sub", | |
633 | "xor", | |
634 | "cmp" | |
635 | }; | |
636 | ||
637 | char * db_Grp2[] = { | |
638 | "rol", | |
639 | "ror", | |
640 | "rcl", | |
641 | "rcr", | |
642 | "shl", | |
643 | "shr", | |
644 | "shl", | |
645 | "sar" | |
646 | }; | |
647 | ||
648 | struct inst db_Grp3[] = { | |
649 | { "test", TRUE, NONE, op2(I,E), 0 }, | |
650 | { "test", TRUE, NONE, op2(I,E), 0 }, | |
651 | { "not", TRUE, NONE, op1(E), 0 }, | |
652 | { "neg", TRUE, NONE, op1(E), 0 }, | |
653 | { "mul", TRUE, NONE, op2(E,A), 0 }, | |
654 | { "imul", TRUE, NONE, op2(E,A), 0 }, | |
655 | { "div", TRUE, NONE, op2(E,A), 0 }, | |
656 | { "idiv", TRUE, NONE, op2(E,A), 0 }, | |
657 | }; | |
658 | ||
659 | struct inst db_Grp4[] = { | |
660 | { "inc", TRUE, BYTE, op1(E), 0 }, | |
661 | { "dec", TRUE, BYTE, op1(E), 0 }, | |
662 | { "", TRUE, NONE, 0, 0 }, | |
663 | { "", TRUE, NONE, 0, 0 }, | |
664 | { "", TRUE, NONE, 0, 0 }, | |
665 | { "", TRUE, NONE, 0, 0 }, | |
666 | { "", TRUE, NONE, 0, 0 }, | |
667 | { "", TRUE, NONE, 0, 0 } | |
668 | }; | |
669 | ||
670 | struct inst db_Grp5[] = { | |
671 | { "inc", TRUE, LONG, op1(E), 0 }, | |
672 | { "dec", TRUE, LONG, op1(E), 0 }, | |
673 | { "call", TRUE, NONE, op1(Eind),0 }, | |
674 | { "lcall", TRUE, NONE, op1(Eind),0 }, | |
675 | { "jmp", TRUE, NONE, op1(Eind),0 }, | |
676 | { "ljmp", TRUE, NONE, op1(Eind),0 }, | |
677 | { "push", TRUE, LONG, op1(E), 0 }, | |
678 | { "", TRUE, NONE, 0, 0 } | |
679 | }; | |
680 | ||
681 | struct inst db_inst_table[256] = { | |
682 | /*00*/ { "add", TRUE, BYTE, op2(R, E), 0 }, | |
683 | /*01*/ { "add", TRUE, LONG, op2(R, E), 0 }, | |
684 | /*02*/ { "add", TRUE, BYTE, op2(E, R), 0 }, | |
685 | /*03*/ { "add", TRUE, LONG, op2(E, R), 0 }, | |
686 | /*04*/ { "add", FALSE, BYTE, op2(Is, A), 0 }, | |
687 | /*05*/ { "add", FALSE, LONG, op2(Is, A), 0 }, | |
688 | /*06*/ { "push", FALSE, NONE, op1(Si), 0 }, | |
689 | /*07*/ { "pop", FALSE, NONE, op1(Si), 0 }, | |
690 | ||
691 | /*08*/ { "or", TRUE, BYTE, op2(R, E), 0 }, | |
692 | /*09*/ { "or", TRUE, LONG, op2(R, E), 0 }, | |
693 | /*0a*/ { "or", TRUE, BYTE, op2(E, R), 0 }, | |
694 | /*0b*/ { "or", TRUE, LONG, op2(E, R), 0 }, | |
695 | /*0c*/ { "or", FALSE, BYTE, op2(I, A), 0 }, | |
696 | /*0d*/ { "or", FALSE, LONG, op2(I, A), 0 }, | |
697 | /*0e*/ { "push", FALSE, NONE, op1(Si), 0 }, | |
698 | /*0f*/ { "", FALSE, NONE, 0, 0 }, | |
699 | ||
700 | /*10*/ { "adc", TRUE, BYTE, op2(R, E), 0 }, | |
701 | /*11*/ { "adc", TRUE, LONG, op2(R, E), 0 }, | |
702 | /*12*/ { "adc", TRUE, BYTE, op2(E, R), 0 }, | |
703 | /*13*/ { "adc", TRUE, LONG, op2(E, R), 0 }, | |
704 | /*14*/ { "adc", FALSE, BYTE, op2(Is, A), 0 }, | |
705 | /*15*/ { "adc", FALSE, LONG, op2(Is, A), 0 }, | |
706 | /*16*/ { "push", FALSE, NONE, op1(Si), 0 }, | |
707 | /*17*/ { "pop", FALSE, NONE, op1(Si), 0 }, | |
708 | ||
709 | /*18*/ { "sbb", TRUE, BYTE, op2(R, E), 0 }, | |
710 | /*19*/ { "sbb", TRUE, LONG, op2(R, E), 0 }, | |
711 | /*1a*/ { "sbb", TRUE, BYTE, op2(E, R), 0 }, | |
712 | /*1b*/ { "sbb", TRUE, LONG, op2(E, R), 0 }, | |
713 | /*1c*/ { "sbb", FALSE, BYTE, op2(Is, A), 0 }, | |
714 | /*1d*/ { "sbb", FALSE, LONG, op2(Is, A), 0 }, | |
715 | /*1e*/ { "push", FALSE, NONE, op1(Si), 0 }, | |
716 | /*1f*/ { "pop", FALSE, NONE, op1(Si), 0 }, | |
717 | ||
718 | /*20*/ { "and", TRUE, BYTE, op2(R, E), 0 }, | |
719 | /*21*/ { "and", TRUE, LONG, op2(R, E), 0 }, | |
720 | /*22*/ { "and", TRUE, BYTE, op2(E, R), 0 }, | |
721 | /*23*/ { "and", TRUE, LONG, op2(E, R), 0 }, | |
722 | /*24*/ { "and", FALSE, BYTE, op2(I, A), 0 }, | |
723 | /*25*/ { "and", FALSE, LONG, op2(I, A), 0 }, | |
724 | /*26*/ { "", FALSE, NONE, 0, 0 }, | |
725 | /*27*/ { "aaa", FALSE, NONE, 0, 0 }, | |
726 | ||
727 | /*28*/ { "sub", TRUE, BYTE, op2(R, E), 0 }, | |
728 | /*29*/ { "sub", TRUE, LONG, op2(R, E), 0 }, | |
729 | /*2a*/ { "sub", TRUE, BYTE, op2(E, R), 0 }, | |
730 | /*2b*/ { "sub", TRUE, LONG, op2(E, R), 0 }, | |
731 | /*2c*/ { "sub", FALSE, BYTE, op2(Is, A), 0 }, | |
732 | /*2d*/ { "sub", FALSE, LONG, op2(Is, A), 0 }, | |
733 | /*2e*/ { "", FALSE, NONE, 0, 0 }, | |
734 | /*2f*/ { "das", FALSE, NONE, 0, 0 }, | |
735 | ||
736 | /*30*/ { "xor", TRUE, BYTE, op2(R, E), 0 }, | |
737 | /*31*/ { "xor", TRUE, LONG, op2(R, E), 0 }, | |
738 | /*32*/ { "xor", TRUE, BYTE, op2(E, R), 0 }, | |
739 | /*33*/ { "xor", TRUE, LONG, op2(E, R), 0 }, | |
740 | /*34*/ { "xor", FALSE, BYTE, op2(I, A), 0 }, | |
741 | /*35*/ { "xor", FALSE, LONG, op2(I, A), 0 }, | |
742 | /*36*/ { "", FALSE, NONE, 0, 0 }, | |
743 | /*37*/ { "daa", FALSE, NONE, 0, 0 }, | |
744 | ||
745 | /*38*/ { "cmp", TRUE, BYTE, op2(R, E), 0 }, | |
746 | /*39*/ { "cmp", TRUE, LONG, op2(R, E), 0 }, | |
747 | /*3a*/ { "cmp", TRUE, BYTE, op2(E, R), 0 }, | |
748 | /*3b*/ { "cmp", TRUE, LONG, op2(E, R), 0 }, | |
749 | /*3c*/ { "cmp", FALSE, BYTE, op2(Is, A), 0 }, | |
750 | /*3d*/ { "cmp", FALSE, LONG, op2(Is, A), 0 }, | |
751 | /*3e*/ { "", FALSE, NONE, 0, 0 }, | |
752 | /*3f*/ { "aas", FALSE, NONE, 0, 0 }, | |
753 | ||
754 | /*40*/ { "inc", FALSE, LONG, op1(Ri), 0 }, | |
755 | /*41*/ { "inc", FALSE, LONG, op1(Ri), 0 }, | |
756 | /*42*/ { "inc", FALSE, LONG, op1(Ri), 0 }, | |
757 | /*43*/ { "inc", FALSE, LONG, op1(Ri), 0 }, | |
758 | /*44*/ { "inc", FALSE, LONG, op1(Ri), 0 }, | |
759 | /*45*/ { "inc", FALSE, LONG, op1(Ri), 0 }, | |
760 | /*46*/ { "inc", FALSE, LONG, op1(Ri), 0 }, | |
761 | /*47*/ { "inc", FALSE, LONG, op1(Ri), 0 }, | |
762 | ||
763 | /*48*/ { "dec", FALSE, LONG, op1(Ri), 0 }, | |
764 | /*49*/ { "dec", FALSE, LONG, op1(Ri), 0 }, | |
765 | /*4a*/ { "dec", FALSE, LONG, op1(Ri), 0 }, | |
766 | /*4b*/ { "dec", FALSE, LONG, op1(Ri), 0 }, | |
767 | /*4c*/ { "dec", FALSE, LONG, op1(Ri), 0 }, | |
768 | /*4d*/ { "dec", FALSE, LONG, op1(Ri), 0 }, | |
769 | /*4e*/ { "dec", FALSE, LONG, op1(Ri), 0 }, | |
770 | /*4f*/ { "dec", FALSE, LONG, op1(Ri), 0 }, | |
771 | ||
772 | /*50*/ { "push", FALSE, LONG, op1(Ri), 0 }, | |
773 | /*51*/ { "push", FALSE, LONG, op1(Ri), 0 }, | |
774 | /*52*/ { "push", FALSE, LONG, op1(Ri), 0 }, | |
775 | /*53*/ { "push", FALSE, LONG, op1(Ri), 0 }, | |
776 | /*54*/ { "push", FALSE, LONG, op1(Ri), 0 }, | |
777 | /*55*/ { "push", FALSE, LONG, op1(Ri), 0 }, | |
778 | /*56*/ { "push", FALSE, LONG, op1(Ri), 0 }, | |
779 | /*57*/ { "push", FALSE, LONG, op1(Ri), 0 }, | |
780 | ||
781 | /*58*/ { "pop", FALSE, LONG, op1(Ri), 0 }, | |
782 | /*59*/ { "pop", FALSE, LONG, op1(Ri), 0 }, | |
783 | /*5a*/ { "pop", FALSE, LONG, op1(Ri), 0 }, | |
784 | /*5b*/ { "pop", FALSE, LONG, op1(Ri), 0 }, | |
785 | /*5c*/ { "pop", FALSE, LONG, op1(Ri), 0 }, | |
786 | /*5d*/ { "pop", FALSE, LONG, op1(Ri), 0 }, | |
787 | /*5e*/ { "pop", FALSE, LONG, op1(Ri), 0 }, | |
788 | /*5f*/ { "pop", FALSE, LONG, op1(Ri), 0 }, | |
789 | ||
790 | /*60*/ { "pusha", FALSE, LONG, 0, 0 }, | |
791 | /*61*/ { "popa", FALSE, LONG, 0, 0 }, | |
792 | /*62*/ { "bound", TRUE, LONG, op2(E, R), 0 }, | |
793 | /*63*/ { "arpl", TRUE, NONE, op2(Ew,Rw), 0 }, | |
794 | ||
795 | /*64*/ { "", FALSE, NONE, 0, 0 }, | |
796 | /*65*/ { "", FALSE, NONE, 0, 0 }, | |
797 | /*66*/ { "", FALSE, NONE, 0, 0 }, | |
798 | /*67*/ { "", FALSE, NONE, 0, 0 }, | |
799 | ||
800 | /*68*/ { "push", FALSE, LONG, op1(I), 0 }, | |
801 | /*69*/ { "imul", TRUE, LONG, op3(I,E,R), 0 }, | |
802 | /*6a*/ { "push", FALSE, LONG, op1(Ib), 0 }, | |
803 | /*6b*/ { "imul", TRUE, LONG, op3(Ibs,E,R),0 }, | |
804 | /*6c*/ { "ins", FALSE, BYTE, op2(DX, DI), 0 }, | |
805 | /*6d*/ { "ins", FALSE, LONG, op2(DX, DI), 0 }, | |
806 | /*6e*/ { "outs", FALSE, BYTE, op2(SI, DX), 0 }, | |
807 | /*6f*/ { "outs", FALSE, LONG, op2(SI, DX), 0 }, | |
808 | ||
809 | /*70*/ { "jo", FALSE, NONE, op1(Db), 0 }, | |
810 | /*71*/ { "jno", FALSE, NONE, op1(Db), 0 }, | |
811 | /*72*/ { "jb", FALSE, NONE, op1(Db), 0 }, | |
812 | /*73*/ { "jnb", FALSE, NONE, op1(Db), 0 }, | |
813 | /*74*/ { "jz", FALSE, NONE, op1(Db), 0 }, | |
814 | /*75*/ { "jnz", FALSE, NONE, op1(Db), 0 }, | |
815 | /*76*/ { "jbe", FALSE, NONE, op1(Db), 0 }, | |
816 | /*77*/ { "jnbe", FALSE, NONE, op1(Db), 0 }, | |
817 | ||
818 | /*78*/ { "js", FALSE, NONE, op1(Db), 0 }, | |
819 | /*79*/ { "jns", FALSE, NONE, op1(Db), 0 }, | |
820 | /*7a*/ { "jp", FALSE, NONE, op1(Db), 0 }, | |
821 | /*7b*/ { "jnp", FALSE, NONE, op1(Db), 0 }, | |
822 | /*7c*/ { "jl", FALSE, NONE, op1(Db), 0 }, | |
823 | /*7d*/ { "jnl", FALSE, NONE, op1(Db), 0 }, | |
824 | /*7e*/ { "jle", FALSE, NONE, op1(Db), 0 }, | |
825 | /*7f*/ { "jnle", FALSE, NONE, op1(Db), 0 }, | |
826 | ||
827 | /*80*/ { "", TRUE, BYTE, op2(I, E), (char *)db_Grp1 }, | |
828 | /*81*/ { "", TRUE, LONG, op2(I, E), (char *)db_Grp1 }, | |
829 | /*82*/ { "", TRUE, BYTE, op2(Is,E), (char *)db_Grp1 }, | |
830 | /*83*/ { "", TRUE, LONG, op2(Ibs,E), (char *)db_Grp1 }, | |
831 | /*84*/ { "test", TRUE, BYTE, op2(R, E), 0 }, | |
832 | /*85*/ { "test", TRUE, LONG, op2(R, E), 0 }, | |
833 | /*86*/ { "xchg", TRUE, BYTE, op2(R, E), 0 }, | |
834 | /*87*/ { "xchg", TRUE, LONG, op2(R, E), 0 }, | |
835 | ||
836 | /*88*/ { "mov", TRUE, BYTE, op2(R, E), 0 }, | |
837 | /*89*/ { "mov", TRUE, LONG, op2(R, E), 0 }, | |
838 | /*8a*/ { "mov", TRUE, BYTE, op2(E, R), 0 }, | |
839 | /*8b*/ { "mov", TRUE, LONG, op2(E, R), 0 }, | |
840 | /*8c*/ { "mov", TRUE, NONE, op2(S, Ew), 0 }, | |
841 | /*8d*/ { "lea", TRUE, LONG, op2(E, R), 0 }, | |
842 | /*8e*/ { "mov", TRUE, NONE, op2(Ew, S), 0 }, | |
843 | /*8f*/ { "pop", TRUE, LONG, op1(E), 0 }, | |
844 | ||
845 | /*90*/ { "nop", FALSE, NONE, 0, 0 }, | |
846 | /*91*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, | |
847 | /*92*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, | |
848 | /*93*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, | |
849 | /*94*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, | |
850 | /*95*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, | |
851 | /*96*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, | |
852 | /*97*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, | |
853 | ||
854 | /*98*/ { "cbw", FALSE, SDEP, 0, "cwde" }, /* cbw/cwde */ | |
855 | /*99*/ { "cwd", FALSE, SDEP, 0, "cdq" }, /* cwd/cdq */ | |
856 | /*9a*/ { "lcall", FALSE, NONE, op1(OS), 0 }, | |
857 | /*9b*/ { "wait", FALSE, NONE, 0, 0 }, | |
858 | /*9c*/ { "pushf", FALSE, LONG, 0, 0 }, | |
859 | /*9d*/ { "popf", FALSE, LONG, 0, 0 }, | |
860 | /*9e*/ { "sahf", FALSE, NONE, 0, 0 }, | |
861 | /*9f*/ { "lahf", FALSE, NONE, 0, 0 }, | |
862 | ||
863 | /*a0*/ { "mov", FALSE, BYTE, op2(O, A), 0 }, | |
864 | /*a1*/ { "mov", FALSE, LONG, op2(O, A), 0 }, | |
865 | /*a2*/ { "mov", FALSE, BYTE, op2(A, O), 0 }, | |
866 | /*a3*/ { "mov", FALSE, LONG, op2(A, O), 0 }, | |
867 | /*a4*/ { "movs", FALSE, BYTE, op2(SI,DI), 0 }, | |
868 | /*a5*/ { "movs", FALSE, LONG, op2(SI,DI), 0 }, | |
869 | /*a6*/ { "cmps", FALSE, BYTE, op2(SI,DI), 0 }, | |
870 | /*a7*/ { "cmps", FALSE, LONG, op2(SI,DI), 0 }, | |
871 | ||
872 | /*a8*/ { "test", FALSE, BYTE, op2(I, A), 0 }, | |
873 | /*a9*/ { "test", FALSE, LONG, op2(I, A), 0 }, | |
874 | /*aa*/ { "stos", FALSE, BYTE, op1(DI), 0 }, | |
875 | /*ab*/ { "stos", FALSE, LONG, op1(DI), 0 }, | |
876 | /*ac*/ { "lods", FALSE, BYTE, op1(SI), 0 }, | |
877 | /*ad*/ { "lods", FALSE, LONG, op1(SI), 0 }, | |
878 | /*ae*/ { "scas", FALSE, BYTE, op1(SI), 0 }, | |
879 | /*af*/ { "scas", FALSE, LONG, op1(SI), 0 }, | |
880 | ||
881 | /*b0*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, | |
882 | /*b1*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, | |
883 | /*b2*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, | |
884 | /*b3*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, | |
885 | /*b4*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, | |
886 | /*b5*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, | |
887 | /*b6*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, | |
888 | /*b7*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, | |
889 | ||
890 | /*b8*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, | |
891 | /*b9*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, | |
892 | /*ba*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, | |
893 | /*bb*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, | |
894 | /*bc*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, | |
895 | /*bd*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, | |
896 | /*be*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, | |
897 | /*bf*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, | |
898 | ||
899 | /*c0*/ { "", TRUE, BYTE, op2(Ib, E), (char *)db_Grp2 }, | |
900 | /*c1*/ { "", TRUE, LONG, op2(Ib, E), (char *)db_Grp2 }, | |
901 | /*c2*/ { "ret", FALSE, NONE, op1(Iw), 0 }, | |
902 | /*c3*/ { "ret", FALSE, NONE, 0, 0 }, | |
903 | /*c4*/ { "les", TRUE, LONG, op2(E, R), 0 }, | |
904 | /*c5*/ { "lds", TRUE, LONG, op2(E, R), 0 }, | |
905 | /*c6*/ { "mov", TRUE, BYTE, op2(I, E), 0 }, | |
906 | /*c7*/ { "mov", TRUE, LONG, op2(I, E), 0 }, | |
907 | ||
908 | /*c8*/ { "enter", FALSE, NONE, op2(Ib, Iw), 0 }, | |
909 | /*c9*/ { "leave", FALSE, NONE, 0, 0 }, | |
910 | /*ca*/ { "lret", FALSE, NONE, op1(Iw), 0 }, | |
911 | /*cb*/ { "lret", FALSE, NONE, 0, 0 }, | |
912 | /*cc*/ { "int", FALSE, NONE, op1(o3), 0 }, | |
913 | /*cd*/ { "int", FALSE, NONE, op1(Ib), 0 }, | |
914 | /*ce*/ { "into", FALSE, NONE, 0, 0 }, | |
915 | /*cf*/ { "iret", FALSE, NONE, 0, 0 }, | |
916 | ||
917 | /*d0*/ { "", TRUE, BYTE, op2(o1, E), (char *)db_Grp2 }, | |
918 | /*d1*/ { "", TRUE, LONG, op2(o1, E), (char *)db_Grp2 }, | |
919 | /*d2*/ { "", TRUE, BYTE, op2(CL, E), (char *)db_Grp2 }, | |
920 | /*d3*/ { "", TRUE, LONG, op2(CL, E), (char *)db_Grp2 }, | |
921 | /*d4*/ { "aam", TRUE, NONE, 0, 0 }, | |
922 | /*d5*/ { "aad", TRUE, NONE, 0, 0 }, | |
923 | /*d6*/ { "", FALSE, NONE, 0, 0 }, | |
924 | /*d7*/ { "xlat", FALSE, BYTE, op1(BX), 0 }, | |
925 | ||
926 | /*d8*/ { "", TRUE, NONE, 0, (char *)db_Esc8 }, | |
927 | /*d9*/ { "", TRUE, NONE, 0, (char *)db_Esc9 }, | |
928 | /*da*/ { "", TRUE, NONE, 0, (char *)db_Esca }, | |
929 | /*db*/ { "", TRUE, NONE, 0, (char *)db_Escb }, | |
930 | /*dc*/ { "", TRUE, NONE, 0, (char *)db_Escc }, | |
931 | /*dd*/ { "", TRUE, NONE, 0, (char *)db_Escd }, | |
932 | /*de*/ { "", TRUE, NONE, 0, (char *)db_Esce }, | |
933 | /*df*/ { "", TRUE, NONE, 0, (char *)db_Escf }, | |
934 | ||
935 | /*e0*/ { "loopne",FALSE, NONE, op1(Db), 0 }, | |
936 | /*e1*/ { "loope", FALSE, NONE, op1(Db), 0 }, | |
937 | /*e2*/ { "loop", FALSE, NONE, op1(Db), 0 }, | |
938 | /*e3*/ { "jcxz", FALSE, SDEP, op1(Db), "jecxz" }, | |
939 | /*e4*/ { "in", FALSE, BYTE, op2(Ib, A), 0 }, | |
940 | /*e5*/ { "in", FALSE, LONG, op2(Ib, A) , 0 }, | |
941 | /*e6*/ { "out", FALSE, BYTE, op2(A, Ib), 0 }, | |
942 | /*e7*/ { "out", FALSE, LONG, op2(A, Ib) , 0 }, | |
943 | ||
944 | /*e8*/ { "call", FALSE, NONE, op1(Dl), 0 }, | |
945 | /*e9*/ { "jmp", FALSE, NONE, op1(Dl), 0 }, | |
946 | /*ea*/ { "ljmp", FALSE, NONE, op1(OS), 0 }, | |
947 | /*eb*/ { "jmp", FALSE, NONE, op1(Db), 0 }, | |
948 | /*ec*/ { "in", FALSE, BYTE, op2(DX, A), 0 }, | |
949 | /*ed*/ { "in", FALSE, LONG, op2(DX, A) , 0 }, | |
950 | /*ee*/ { "out", FALSE, BYTE, op2(A, DX), 0 }, | |
951 | /*ef*/ { "out", FALSE, LONG, op2(A, DX) , 0 }, | |
952 | ||
953 | /*f0*/ { "", FALSE, NONE, 0, 0 }, | |
954 | /*f1*/ { "", FALSE, NONE, 0, 0 }, | |
955 | /*f2*/ { "", FALSE, NONE, 0, 0 }, | |
956 | /*f3*/ { "", FALSE, NONE, 0, 0 }, | |
957 | /*f4*/ { "hlt", FALSE, NONE, 0, 0 }, | |
958 | /*f5*/ { "cmc", FALSE, NONE, 0, 0 }, | |
959 | /*f6*/ { "", TRUE, BYTE, 0, (char *)db_Grp3 }, | |
960 | /*f7*/ { "", TRUE, LONG, 0, (char *)db_Grp3 }, | |
961 | ||
962 | /*f8*/ { "clc", FALSE, NONE, 0, 0 }, | |
963 | /*f9*/ { "stc", FALSE, NONE, 0, 0 }, | |
964 | /*fa*/ { "cli", FALSE, NONE, 0, 0 }, | |
965 | /*fb*/ { "sti", FALSE, NONE, 0, 0 }, | |
966 | /*fc*/ { "cld", FALSE, NONE, 0, 0 }, | |
967 | /*fd*/ { "std", FALSE, NONE, 0, 0 }, | |
968 | /*fe*/ { "", TRUE, NONE, 0, (char *)db_Grp4 }, | |
969 | /*ff*/ { "", TRUE, NONE, 0, (char *)db_Grp5 }, | |
970 | }; | |
971 | ||
972 | struct inst db_bad_inst = | |
973 | { "???", FALSE, NONE, 0, 0 } | |
974 | ; | |
975 | ||
976 | #define f_mod(byte) ((byte)>>6) | |
977 | #define f_reg(byte) (((byte)>>3)&0x7) | |
978 | #define f_rm(byte) ((byte)&0x7) | |
979 | ||
980 | #define sib_ss(byte) ((byte)>>6) | |
981 | #define sib_index(byte) (((byte)>>3)&0x7) | |
982 | #define sib_base(byte) ((byte)&0x7) | |
983 | ||
984 | char * db_index_reg_16[8] = { | |
985 | "%bx,%si", | |
986 | "%bx,%di", | |
987 | "%bp,%si", | |
988 | "%bp,%di", | |
989 | "%si", | |
990 | "%di", | |
991 | "%bp", | |
992 | "%bx" | |
993 | }; | |
994 | ||
995 | char * db_reg[3][8] = { | |
996 | "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", | |
997 | "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", | |
998 | "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" | |
999 | }; | |
1000 | ||
1001 | char * db_seg_reg[8] = { | |
1002 | "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", "" | |
1003 | }; | |
1004 | ||
1005 | /* | |
1006 | * lengths for size attributes | |
1007 | */ | |
1008 | int db_lengths[] = { | |
1009 | 1, /* BYTE */ | |
1010 | 2, /* WORD */ | |
1011 | 4, /* LONG */ | |
1012 | 8, /* QUAD */ | |
1013 | 4, /* SNGL */ | |
1014 | 8, /* DBLR */ | |
1015 | 10, /* EXTR */ | |
1016 | }; | |
1017 | ||
1018 | #define get_value_inc(result, loc, size, is_signed, task) \ | |
1019 | result = db_get_task_value((loc), (size), (is_signed), (task)); \ | |
1020 | (loc) += (size); | |
1021 | ||
1022 | /* | |
1023 | * Read address at location and return updated location. | |
1024 | */ | |
1025 | db_addr_t | |
1026 | db_read_address( | |
1027 | db_addr_t loc, | |
1028 | int short_addr, | |
1029 | int regmodrm, | |
1030 | struct i_addr *addrp, /* out */ | |
1031 | task_t task) | |
1032 | { | |
1033 | int mod, rm, sib, index, ss, disp; | |
1034 | ||
1035 | mod = f_mod(regmodrm); | |
1036 | rm = f_rm(regmodrm); | |
1037 | ||
1038 | if (mod == 3) { | |
1039 | addrp->is_reg = TRUE; | |
1040 | addrp->disp = rm; | |
1041 | return (loc); | |
1042 | } | |
1043 | addrp->is_reg = FALSE; | |
1044 | addrp->index = 0; | |
1045 | ||
1046 | if (short_addr) { | |
1047 | addrp->index = 0; | |
1048 | addrp->ss = 0; | |
1049 | switch (mod) { | |
1050 | case 0: | |
1051 | if (rm == 6) { | |
1052 | get_value_inc(disp, loc, 2, TRUE, task); | |
1053 | addrp->disp = disp; | |
1054 | addrp->base = 0; | |
1055 | } | |
1056 | else { | |
1057 | addrp->disp = 0; | |
1058 | addrp->base = db_index_reg_16[rm]; | |
1059 | } | |
1060 | break; | |
1061 | case 1: | |
1062 | get_value_inc(disp, loc, 1, TRUE, task); | |
1063 | addrp->disp = disp; | |
1064 | addrp->base = db_index_reg_16[rm]; | |
1065 | break; | |
1066 | case 2: | |
1067 | get_value_inc(disp, loc, 2, TRUE, task); | |
1068 | addrp->disp = disp; | |
1069 | addrp->base = db_index_reg_16[rm]; | |
1070 | break; | |
1071 | } | |
1072 | } | |
1073 | else { | |
1074 | if (mod != 3 && rm == 4) { | |
1075 | get_value_inc(sib, loc, 1, FALSE, task); | |
1076 | rm = sib_base(sib); | |
1077 | index = sib_index(sib); | |
1078 | if (index != 4) | |
1079 | addrp->index = db_reg[LONG][index]; | |
1080 | addrp->ss = sib_ss(sib); | |
1081 | } | |
1082 | ||
1083 | switch (mod) { | |
1084 | case 0: | |
1085 | if (rm == 5) { | |
1086 | get_value_inc(addrp->disp, loc, 4, FALSE, task); | |
1087 | addrp->base = 0; | |
1088 | } | |
1089 | else { | |
1090 | addrp->disp = 0; | |
1091 | addrp->base = db_reg[LONG][rm]; | |
1092 | } | |
1093 | break; | |
1094 | ||
1095 | case 1: | |
1096 | get_value_inc(disp, loc, 1, TRUE, task); | |
1097 | addrp->disp = disp; | |
1098 | addrp->base = db_reg[LONG][rm]; | |
1099 | break; | |
1100 | ||
1101 | case 2: | |
1102 | get_value_inc(disp, loc, 4, FALSE, task); | |
1103 | addrp->disp = disp; | |
1104 | addrp->base = db_reg[LONG][rm]; | |
1105 | break; | |
1106 | } | |
1107 | } | |
1108 | return (loc); | |
1109 | } | |
1110 | ||
1111 | void | |
1112 | db_print_address( | |
1113 | char * seg, | |
1114 | int size, | |
1115 | struct i_addr *addrp, | |
1116 | task_t task) | |
1117 | { | |
1118 | if (addrp->is_reg) { | |
1119 | db_printf("%s", db_reg[size][addrp->disp]); | |
1120 | return; | |
1121 | } | |
1122 | ||
1123 | if (seg) { | |
1124 | db_printf("%s:", seg); | |
1125 | } | |
1126 | ||
1127 | if (addrp->base != 0 || addrp->index != 0) { | |
1128 | db_printf("%#n", addrp->disp); | |
1129 | db_printf("("); | |
1130 | if (addrp->base) | |
1131 | db_printf("%s", addrp->base); | |
1132 | if (addrp->index) | |
1133 | db_printf(",%s,%d", addrp->index, 1<<addrp->ss); | |
1134 | db_printf(")"); | |
1135 | } else | |
1136 | db_task_printsym((db_addr_t)addrp->disp, DB_STGY_ANY, task); | |
1137 | } | |
1138 | ||
1139 | /* | |
1140 | * Disassemble floating-point ("escape") instruction | |
1141 | * and return updated location. | |
1142 | */ | |
1143 | db_addr_t | |
1144 | db_disasm_esc( | |
1145 | db_addr_t loc, | |
1146 | int inst, | |
1147 | int short_addr, | |
1148 | int size, | |
1149 | char * seg, | |
1150 | task_t task) | |
1151 | { | |
1152 | int regmodrm; | |
1153 | struct finst *fp; | |
1154 | int mod; | |
1155 | struct i_addr address; | |
1156 | char * name; | |
1157 | ||
1158 | get_value_inc(regmodrm, loc, 1, FALSE, task); | |
1159 | fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)]; | |
1160 | mod = f_mod(regmodrm); | |
1161 | if (mod != 3) { | |
1162 | /* | |
1163 | * Normal address modes. | |
1164 | */ | |
1165 | loc = db_read_address(loc, short_addr, regmodrm, &address, task); | |
1166 | db_printf(fp->f_name); | |
1167 | switch(fp->f_size) { | |
1168 | case SNGL: | |
1169 | db_printf("s"); | |
1170 | break; | |
1171 | case DBLR: | |
1172 | db_printf("l"); | |
1173 | break; | |
1174 | case EXTR: | |
1175 | db_printf("t"); | |
1176 | break; | |
1177 | case WORD: | |
1178 | db_printf("s"); | |
1179 | break; | |
1180 | case LONG: | |
1181 | db_printf("l"); | |
1182 | break; | |
1183 | case QUAD: | |
1184 | db_printf("q"); | |
1185 | break; | |
1186 | default: | |
1187 | break; | |
1188 | } | |
1189 | db_printf("\t"); | |
1190 | db_print_address(seg, BYTE, &address, task); | |
1191 | } | |
1192 | else { | |
1193 | /* | |
1194 | * 'reg-reg' - special formats | |
1195 | */ | |
1196 | switch (fp->f_rrmode) { | |
1197 | case op2(ST,STI): | |
1198 | name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | |
1199 | db_printf("%s\t%%st,%%st(%d)",name,f_rm(regmodrm)); | |
1200 | break; | |
1201 | case op2(STI,ST): | |
1202 | name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | |
1203 | db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm)); | |
1204 | break; | |
1205 | case op1(STI): | |
1206 | name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | |
1207 | db_printf("%s\t%%st(%d)",name, f_rm(regmodrm)); | |
1208 | break; | |
1209 | case op1(X): | |
1210 | db_printf("%s", ((char **)fp->f_rrname)[f_rm(regmodrm)]); | |
1211 | break; | |
1212 | case op1(XA): | |
1213 | db_printf("%s\t%%ax", | |
1214 | ((char **)fp->f_rrname)[f_rm(regmodrm)]); | |
1215 | break; | |
1216 | default: | |
1217 | db_printf("<bad instruction>"); | |
1218 | break; | |
1219 | } | |
1220 | } | |
1221 | ||
1222 | return (loc); | |
1223 | } | |
1224 | ||
1225 | /* | |
1226 | * Disassemble instruction at 'loc'. 'altfmt' specifies an | |
1227 | * (optional) alternate format. Return address of start of | |
1228 | * next instruction. | |
1229 | */ | |
1230 | db_addr_t | |
1231 | db_disasm( | |
1232 | db_addr_t loc, | |
1233 | boolean_t altfmt, | |
1234 | task_t task) | |
1235 | { | |
1236 | int inst; | |
1237 | int size; | |
1238 | int short_addr; | |
1239 | char * seg; | |
1240 | struct inst * ip; | |
1241 | char * i_name; | |
1242 | int i_size; | |
1243 | int i_mode; | |
1244 | int regmodrm; | |
1245 | boolean_t first; | |
1246 | int displ; | |
1247 | int prefix; | |
1248 | int imm; | |
1249 | int imm2; | |
1250 | int len; | |
1251 | struct i_addr address; | |
1252 | char *filename; | |
1253 | int linenum; | |
1254 | ||
1255 | get_value_inc(inst, loc, 1, FALSE, task); | |
1256 | if (db_disasm_16) { | |
1257 | short_addr = TRUE; | |
1258 | size = WORD; | |
1259 | } | |
1260 | else { | |
1261 | short_addr = FALSE; | |
1262 | size = LONG; | |
1263 | } | |
1264 | seg = 0; | |
1265 | ||
1266 | /* | |
1267 | * Get prefixes | |
1268 | */ | |
1269 | prefix = TRUE; | |
1270 | do { | |
1271 | switch (inst) { | |
1272 | case 0x66: /* data16 */ | |
1273 | if (size == LONG) | |
1274 | size = WORD; | |
1275 | else | |
1276 | size = LONG; | |
1277 | break; | |
1278 | case 0x67: | |
1279 | short_addr = !short_addr; | |
1280 | break; | |
1281 | case 0x26: | |
1282 | seg = "%es"; | |
1283 | break; | |
1284 | case 0x36: | |
1285 | seg = "%ss"; | |
1286 | break; | |
1287 | case 0x2e: | |
1288 | seg = "%cs"; | |
1289 | break; | |
1290 | case 0x3e: | |
1291 | seg = "%ds"; | |
1292 | break; | |
1293 | case 0x64: | |
1294 | seg = "%fs"; | |
1295 | break; | |
1296 | case 0x65: | |
1297 | seg = "%gs"; | |
1298 | break; | |
1299 | case 0xf0: | |
1300 | db_printf("lock "); | |
1301 | break; | |
1302 | case 0xf2: | |
1303 | db_printf("repne "); | |
1304 | break; | |
1305 | case 0xf3: | |
1306 | db_printf("repe "); /* XXX repe VS rep */ | |
1307 | break; | |
1308 | default: | |
1309 | prefix = FALSE; | |
1310 | break; | |
1311 | } | |
1312 | if (prefix) { | |
1313 | get_value_inc(inst, loc, 1, FALSE, task); | |
1314 | } | |
1315 | } while (prefix); | |
1316 | ||
1317 | if (inst >= 0xd8 && inst <= 0xdf) { | |
1318 | loc = db_disasm_esc(loc, inst, short_addr, size, seg, task); | |
1319 | db_printf("\n"); | |
1320 | return (loc); | |
1321 | } | |
1322 | ||
1323 | if (inst == 0x0f) { | |
1324 | get_value_inc(inst, loc, 1, FALSE, task); | |
1325 | ip = db_inst_0f[inst>>4]; | |
1326 | if (ip == 0) { | |
1327 | ip = &db_bad_inst; | |
1328 | } | |
1329 | else { | |
1330 | ip = &ip[inst&0xf]; | |
1331 | } | |
1332 | } | |
1333 | else | |
1334 | ip = &db_inst_table[inst]; | |
1335 | ||
1336 | if (ip->i_has_modrm) { | |
1337 | get_value_inc(regmodrm, loc, 1, FALSE, task); | |
1338 | loc = db_read_address(loc, short_addr, regmodrm, &address, task); | |
1339 | } | |
1340 | ||
1341 | i_name = ip->i_name; | |
1342 | i_size = ip->i_size; | |
1343 | i_mode = ip->i_mode; | |
1344 | ||
1345 | if (ip->i_extra == (char *)db_Grp1 || | |
1346 | ip->i_extra == (char *)db_Grp2 || | |
1347 | ip->i_extra == (char *)db_Grp6 || | |
1348 | ip->i_extra == (char *)db_Grp7 || | |
1349 | ip->i_extra == (char *)db_Grp8) { | |
1350 | i_name = ((char **)ip->i_extra)[f_reg(regmodrm)]; | |
1351 | } | |
1352 | else if (ip->i_extra == (char *)db_Grp3) { | |
1353 | ip = (struct inst *)ip->i_extra; | |
1354 | ip = &ip[f_reg(regmodrm)]; | |
1355 | i_name = ip->i_name; | |
1356 | i_mode = ip->i_mode; | |
1357 | } | |
1358 | else if (ip->i_extra == (char *)db_Grp4 || | |
1359 | ip->i_extra == (char *)db_Grp5) { | |
1360 | ip = (struct inst *)ip->i_extra; | |
1361 | ip = &ip[f_reg(regmodrm)]; | |
1362 | i_name = ip->i_name; | |
1363 | i_mode = ip->i_mode; | |
1364 | i_size = ip->i_size; | |
1365 | } | |
1366 | ||
1367 | if (i_size == SDEP) { | |
1368 | if (size == WORD) | |
1369 | db_printf(i_name); | |
1370 | else | |
1371 | db_printf(ip->i_extra); | |
1372 | } | |
1373 | else { | |
1374 | db_printf(i_name); | |
1375 | if (i_size != NONE) { | |
1376 | if (i_size == BYTE) { | |
1377 | db_printf("b"); | |
1378 | size = BYTE; | |
1379 | } | |
1380 | else if (i_size == WORD) { | |
1381 | db_printf("w"); | |
1382 | size = WORD; | |
1383 | } | |
1384 | else if (size == WORD) | |
1385 | db_printf("w"); | |
1386 | else | |
1387 | db_printf("l"); | |
1388 | } | |
1389 | } | |
1390 | db_printf("\t"); | |
1391 | for (first = TRUE; | |
1392 | i_mode != 0; | |
1393 | i_mode >>= 8, first = FALSE) | |
1394 | { | |
1395 | if (!first) | |
1396 | db_printf(","); | |
1397 | ||
1398 | switch (i_mode & 0xFF) { | |
1399 | ||
1400 | case E: | |
1401 | db_print_address(seg, size, &address, task); | |
1402 | break; | |
1403 | ||
1404 | case Eind: | |
1405 | db_printf("*"); | |
1406 | db_print_address(seg, size, &address, task); | |
1407 | break; | |
1408 | ||
1409 | case Ew: | |
1410 | db_print_address(seg, WORD, &address, task); | |
1411 | break; | |
1412 | ||
1413 | case Eb: | |
1414 | db_print_address(seg, BYTE, &address, task); | |
1415 | break; | |
1416 | ||
1417 | case R: | |
1418 | db_printf("%s", db_reg[size][f_reg(regmodrm)]); | |
1419 | break; | |
1420 | ||
1421 | case Rw: | |
1422 | db_printf("%s", db_reg[WORD][f_reg(regmodrm)]); | |
1423 | break; | |
1424 | ||
1425 | case Ri: | |
1426 | db_printf("%s", db_reg[size][f_rm(inst)]); | |
1427 | break; | |
1428 | ||
1429 | case S: | |
1430 | db_printf("%s", db_seg_reg[f_reg(regmodrm)]); | |
1431 | break; | |
1432 | ||
1433 | case Si: | |
1434 | db_printf("%s", db_seg_reg[f_reg(inst)]); | |
1435 | break; | |
1436 | ||
1437 | case A: | |
1438 | db_printf("%s", db_reg[size][0]); /* acc */ | |
1439 | break; | |
1440 | ||
1441 | case BX: | |
1442 | if (seg) | |
1443 | db_printf("%s:", seg); | |
1444 | db_printf("(%s)", short_addr ? "%bx" : "%ebx"); | |
1445 | break; | |
1446 | ||
1447 | case CL: | |
1448 | db_printf("%%cl"); | |
1449 | break; | |
1450 | ||
1451 | case DX: | |
1452 | db_printf("%%dx"); | |
1453 | break; | |
1454 | ||
1455 | case SI: | |
1456 | if (seg) | |
1457 | db_printf("%s:", seg); | |
1458 | db_printf("(%s)", short_addr ? "%si" : "%esi"); | |
1459 | break; | |
1460 | ||
1461 | case DI: | |
1462 | db_printf("%%es:(%s)", short_addr ? "%di" : "%edi"); | |
1463 | break; | |
1464 | ||
1465 | case CR: | |
1466 | db_printf("%%cr%d", f_reg(regmodrm)); | |
1467 | break; | |
1468 | ||
1469 | case DR: | |
1470 | db_printf("%%dr%d", f_reg(regmodrm)); | |
1471 | break; | |
1472 | ||
1473 | case TR: | |
1474 | db_printf("%%tr%d", f_reg(regmodrm)); | |
1475 | break; | |
1476 | ||
1477 | case I: | |
1478 | len = db_lengths[size]; | |
1479 | get_value_inc(imm, loc, len, FALSE, task);/* unsigned */ | |
1480 | db_printf("$%#n", imm); | |
1481 | break; | |
1482 | ||
1483 | case Is: | |
1484 | len = db_lengths[size]; | |
1485 | get_value_inc(imm, loc, len, TRUE, task); /* signed */ | |
1486 | db_printf("$%#r", imm); | |
1487 | break; | |
1488 | ||
1489 | case Ib: | |
1490 | get_value_inc(imm, loc, 1, FALSE, task); /* unsigned */ | |
1491 | db_printf("$%#n", imm); | |
1492 | break; | |
1493 | ||
1494 | case Ibs: | |
1495 | get_value_inc(imm, loc, 1, TRUE, task); /* signed */ | |
1496 | db_printf("$%#r", imm); | |
1497 | break; | |
1498 | ||
1499 | case Iw: | |
1500 | get_value_inc(imm, loc, 2, FALSE, task); /* unsigned */ | |
1501 | db_printf("$%#n", imm); | |
1502 | break; | |
1503 | ||
1504 | case Il: | |
1505 | get_value_inc(imm, loc, 4, FALSE, task); | |
1506 | db_printf("$%#n", imm); | |
1507 | break; | |
1508 | ||
1509 | case O: | |
1510 | if (short_addr) { | |
1511 | get_value_inc(displ, loc, 2, TRUE, task); | |
1512 | } | |
1513 | else { | |
1514 | get_value_inc(displ, loc, 4, TRUE, task); | |
1515 | } | |
1516 | if (seg) | |
1517 | db_printf("%s:%#r",seg, displ); | |
1518 | else | |
1519 | db_task_printsym((db_addr_t)displ, DB_STGY_ANY, task); | |
1520 | break; | |
1521 | ||
1522 | case Db: | |
1523 | get_value_inc(displ, loc, 1, TRUE, task); | |
1524 | if (short_addr) { | |
1525 | /* offset only affects low 16 bits */ | |
1526 | displ = (loc & 0xffff0000) | |
1527 | | ((loc + displ) & 0xffff); | |
1528 | } | |
1529 | else | |
1530 | displ = displ + loc; | |
1531 | db_task_printsym((db_addr_t)displ,DB_STGY_ANY,task); | |
1532 | if (db_line_at_pc(0, &filename, &linenum, displ)) { | |
1533 | db_printf(" [%s", filename); | |
1534 | if (linenum > 0) | |
1535 | db_printf(":%d", linenum); | |
1536 | db_printf("]"); | |
1537 | } | |
1538 | break; | |
1539 | ||
1540 | case Dl: | |
1541 | if (short_addr) { | |
1542 | get_value_inc(displ, loc, 2, TRUE, task); | |
1543 | /* offset only affects low 16 bits */ | |
1544 | displ = (loc & 0xffff0000) | |
1545 | | ((loc + displ) & 0xffff); | |
1546 | } | |
1547 | else { | |
1548 | get_value_inc(displ, loc, 4, TRUE, task); | |
1549 | displ = displ + loc; | |
1550 | } | |
1551 | db_task_printsym((db_addr_t)displ, DB_STGY_ANY, task); | |
1552 | if (db_line_at_pc(0, &filename, &linenum, displ)) { | |
1553 | db_printf(" [%s", filename); | |
1554 | if (linenum > 0) | |
1555 | db_printf(":%d", linenum); | |
1556 | db_printf("]"); | |
1557 | } | |
1558 | break; | |
1559 | ||
1560 | case o1: | |
1561 | db_printf("$1"); | |
1562 | break; | |
1563 | ||
1564 | case o3: | |
1565 | db_printf("$3"); | |
1566 | break; | |
1567 | ||
1568 | case OS: | |
1569 | if (short_addr) { | |
1570 | get_value_inc(imm, loc, 2, FALSE, task); /* offset */ | |
1571 | } | |
1572 | else { | |
1573 | get_value_inc(imm, loc, 4, FALSE, task); /* offset */ | |
1574 | } | |
1575 | get_value_inc(imm2, loc, 2, FALSE, task); /* segment */ | |
1576 | db_printf("$%#n,%#n", imm2, imm); | |
1577 | break; | |
1578 | } | |
1579 | } | |
1580 | ||
1581 | if (altfmt == 0 && !db_disasm_16) { | |
1582 | if (inst == 0xe9 || inst == 0xeb) { /* jmp, Dl or Db */ | |
1583 | /* | |
1584 | * GAS pads to longword boundary after unconditional jumps. | |
1585 | */ | |
1586 | while (loc & (4-1)) { | |
1587 | get_value_inc(inst, loc, 0, FALSE, task); | |
1588 | if (inst != 0x90) /* nop */ | |
1589 | break; | |
1590 | loc++; | |
1591 | } | |
1592 | } | |
1593 | } | |
1594 | db_printf("\n"); | |
1595 | return (loc); | |
1596 | } | |
1597 | ||
1598 | /* | |
1599 | * Classify instructions by whether they read or write memory. | |
1600 | */ | |
1601 | ||
1602 | #define DBLS_LOAD 0x01 /* instruction reads from memory */ | |
1603 | #define DBLS_STORE 0x02 /* instruction writes to memory */ | |
1604 | ||
1605 | #define DBLS_MODRM 0x10 /* instruction uses mod r/m byte */ | |
1606 | #define DBLS_SECOND 0x20 /* instruction does two operations */ | |
1607 | #define DBLS_ESCAPE 0x40 /* escape to two-byte opcodes */ | |
1608 | #define DBLS_SWREG 0x80 /* need to switch on reg bits of mod r/m */ | |
1609 | ||
1610 | #define DBLS_MODS 0xf0 | |
1611 | #define DBLS_LMASK (DBLS_MODS|DBLS_LOAD) | |
1612 | #define DBLS_SMASK (DBLS_MODS|DBLS_STORE) | |
1613 | ||
1614 | char db_ldstrtab[] = { | |
1615 | 0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x02, 0x01, | |
1616 | 0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x02, 0x40, | |
1617 | 0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x02, 0x01, | |
1618 | 0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x02, 0x01, | |
1619 | 0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, | |
1620 | 0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, | |
1621 | 0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, | |
1622 | 0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, | |
1623 | ||
1624 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1625 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1626 | 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, | |
1627 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | |
1628 | 0x02, 0x01, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, | |
1629 | 0x02, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1630 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1631 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1632 | ||
1633 | 0x12, 0x12, 0x00, 0x12, 0x11, 0x11, 0x13, 0x13, | |
1634 | 0x12, 0x12, 0x11, 0x11, 0x12, 0x00, 0x11, 0x03, | |
1635 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1636 | 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00, 0x00, | |
1637 | 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x21, 0x21, | |
1638 | 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, | |
1639 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1640 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1641 | ||
1642 | 0x13, 0x13, 0x00, 0x00, 0x01, 0x01, 0x12, 0x12, | |
1643 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1644 | 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x01, | |
1645 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1646 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1647 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1648 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x13, | |
1649 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x13, | |
1650 | }; | |
1651 | ||
1652 | unsigned char db_ldstrtab0f[] = { | |
1653 | 0x80, 0x80, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, | |
1654 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1655 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1656 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1657 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1658 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1659 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1660 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1661 | ||
1662 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1663 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1664 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1665 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1666 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1667 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1668 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1669 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1670 | ||
1671 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1672 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1673 | 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, | |
1674 | 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, | |
1675 | 0x02, 0x01, 0x00, 0x11, 0x13, 0x13, 0x00, 0x00, | |
1676 | 0x02, 0x01, 0x12, 0x13, 0x13, 0x13, 0x00, 0x11, | |
1677 | 0x00, 0x00, 0x01, 0x13, 0x01, 0x01, 0x11, 0x11, | |
1678 | 0x00, 0x00, 0x80, 0x13, 0x13, 0x13, 0x11, 0x11, | |
1679 | ||
1680 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1681 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1682 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1683 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1684 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1685 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1686 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1687 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1688 | }; | |
1689 | ||
1690 | int db_inst_swreg(boolean_t, unsigned long, unsigned char); | |
1691 | ||
1692 | /* | |
1693 | * Given four bytes of instruction (stored as an int, not an | |
1694 | * array of characters), compute if the instruction reads | |
1695 | * memory. | |
1696 | */ | |
1697 | int | |
1698 | db_inst_load( | |
1699 | unsigned long insw) | |
1700 | { | |
1701 | unsigned char insb, bits; | |
1702 | ||
1703 | insb = insw & 0xff; | |
1704 | insw >>= 8; | |
1705 | bits = db_ldstrtab[insb]; | |
1706 | if (!(bits & DBLS_LOAD)) | |
1707 | return (0); | |
1708 | while (1) { | |
1709 | switch (bits & DBLS_MODS) { | |
1710 | case 0: | |
1711 | return (1); | |
1712 | case DBLS_MODRM: | |
1713 | insb = insw & 0xff; | |
1714 | return ((insb & 0xc0) != 0xc0); | |
1715 | case DBLS_SECOND|DBLS_MODRM: | |
1716 | insb = insw & 0xff; | |
1717 | return ((insb & 0xc0) != 0xc0 ? 2 : 0); | |
1718 | case DBLS_SECOND: | |
1719 | return (2); | |
1720 | case DBLS_ESCAPE: | |
1721 | insb = insw & 0xff; | |
1722 | insw >>= 8; | |
1723 | bits = db_ldstrtab0f[insb]; | |
1724 | break; | |
1725 | case DBLS_SWREG: | |
1726 | return (db_inst_swreg(TRUE, insw, insb)); | |
1727 | default: | |
1728 | panic ("db_inst_load: unknown mod bits"); | |
1729 | } | |
1730 | } | |
1731 | } | |
1732 | ||
1733 | /* | |
1734 | * Given four bytes of instruction (stored as an int, not an | |
1735 | * array of characters), compute if the instruction writes | |
1736 | * memory. | |
1737 | */ | |
1738 | int | |
1739 | db_inst_store( | |
1740 | unsigned long insw) | |
1741 | { | |
1742 | unsigned char insb, bits; | |
1743 | ||
1744 | insb = insw & 0xff; | |
1745 | insw >>= 8; | |
1746 | bits = db_ldstrtab[insb]; | |
1747 | if (!(bits & DBLS_STORE)) | |
1748 | return (0); | |
1749 | while (1) { | |
1750 | switch (bits & DBLS_MODS) { | |
1751 | case 0: | |
1752 | return (1); | |
1753 | case DBLS_MODRM: | |
1754 | insb = insw & 0xff; | |
1755 | return ((insb & 0xc0) != 0xc0); | |
1756 | case DBLS_SECOND|DBLS_MODRM: | |
1757 | insb = insw & 0xff; | |
1758 | return ((insb & 0xc0) != 0xc0 ? 2 : 0); | |
1759 | case DBLS_SECOND: | |
1760 | return (2); | |
1761 | case DBLS_ESCAPE: | |
1762 | insb = insw & 0xff; | |
1763 | insw >>= 8; | |
1764 | bits = db_ldstrtab0f[insb]; | |
1765 | break; | |
1766 | case DBLS_SWREG: | |
1767 | return (db_inst_swreg(FALSE, insw, insb)); | |
1768 | default: | |
1769 | panic ("db_inst_store: unknown mod bits"); | |
1770 | } | |
1771 | } | |
1772 | } | |
1773 | ||
1774 | /* | |
1775 | * Parse a mod r/m byte to see if extended opcode reads | |
1776 | * or writes memory. | |
1777 | */ | |
1778 | int | |
1779 | db_inst_swreg( | |
1780 | boolean_t isload, | |
1781 | unsigned long insw, | |
1782 | unsigned char insb) | |
1783 | { | |
1784 | unsigned char modrm = insw & 0xff; | |
1785 | ||
1786 | switch (insb) { | |
1787 | case 0x00: | |
1788 | switch (modrm & 0x38) { | |
1789 | case 0x00: | |
1790 | case 0x08: | |
1791 | case 0x10: | |
1792 | case 0x18: | |
1793 | return ((modrm & 0xc0) != 0xc0); | |
1794 | } | |
1795 | break; | |
1796 | case 0x01: | |
1797 | switch (modrm & 0x38) { | |
1798 | case 0x00: | |
1799 | case 0x08: | |
1800 | case 0x10: | |
1801 | case 0x18: | |
1802 | return ((modrm & 0xc0) != 0xc0 ? 2 : 0); | |
1803 | case 0x20: | |
1804 | case 0x30: | |
1805 | return ((modrm & 0xc0) != 0xc0); | |
1806 | } | |
1807 | break; | |
1808 | case 0xba: | |
1809 | if (isload) | |
1810 | return ((modrm & 0xc0) != 0xc0); | |
1811 | switch (modrm & 0x38) { | |
1812 | case 0x28: | |
1813 | case 0x30: | |
1814 | case 0x38: | |
1815 | return ((modrm & 0xc0) != 0xc0); | |
1816 | } | |
1817 | break; | |
1818 | } | |
1819 | return (0); | |
1820 | } |