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