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