File: | arch/amd64/amd64/db_disasm.c |
Warning: | line 957, column 6 Branch condition evaluates to a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: db_disasm.c,v 1.22 2020/09/11 09:27:09 mpi Exp $ */ | |||
2 | /* $NetBSD: db_disasm.c,v 1.11 1996/05/03 19:41:58 christos Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Mach Operating System | |||
6 | * Copyright (c) 1991,1990 Carnegie Mellon University | |||
7 | * All Rights Reserved. | |||
8 | * | |||
9 | * Permission to use, copy, modify and distribute this software and its | |||
10 | * documentation is hereby granted, provided that both the copyright | |||
11 | * notice and this permission notice appear in all copies of the | |||
12 | * software, derivative works or modified versions, and any portions | |||
13 | * thereof, and that both notices appear in supporting documentation. | |||
14 | * | |||
15 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |||
16 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |||
17 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |||
18 | * | |||
19 | * Carnegie Mellon requests users of this software to return to | |||
20 | * | |||
21 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |||
22 | * School of Computer Science | |||
23 | * Carnegie Mellon University | |||
24 | * Pittsburgh PA 15213-3890 | |||
25 | * | |||
26 | * any improvements or extensions that they make and grant Carnegie Mellon | |||
27 | * the rights to redistribute these changes. | |||
28 | * | |||
29 | * Id: db_disasm.c,v 2.6 92/01/03 20:05:00 dbg (CMU) | |||
30 | */ | |||
31 | ||||
32 | /* | |||
33 | * Instruction disassembler. | |||
34 | */ | |||
35 | #include <sys/param.h> | |||
36 | #include <sys/systm.h> | |||
37 | #include <machine/db_machdep.h> | |||
38 | ||||
39 | #include <ddb/db_access.h> | |||
40 | #include <ddb/db_sym.h> | |||
41 | #include <ddb/db_output.h> | |||
42 | ||||
43 | /* | |||
44 | * Size attributes | |||
45 | */ | |||
46 | #define BYTE0 0 | |||
47 | #define WORD1 1 | |||
48 | #define LONG2 2 | |||
49 | #define QUAD3 3 | |||
50 | #define SNGL4 4 | |||
51 | #define DBLR5 5 | |||
52 | #define EXTR6 6 | |||
53 | #define SDEP7 7 | |||
54 | #define NONE8 8 | |||
55 | #define RDEP9 9 | |||
56 | ||||
57 | /* | |||
58 | * Addressing modes | |||
59 | */ | |||
60 | #define E1 1 /* general effective address */ | |||
61 | #define Eind2 2 /* indirect address (jump, call) */ | |||
62 | #define Ew3 3 /* address, word size */ | |||
63 | #define Eb4 4 /* address, byte size */ | |||
64 | #define R5 5 /* register, in 'reg' field */ | |||
65 | #define Rw6 6 /* word register, in 'reg' field */ | |||
66 | #define Ri7 7 /* register in instruction */ | |||
67 | #define S8 8 /* segment reg, in 'reg' field */ | |||
68 | #define Si9 9 /* segment reg, in instruction */ | |||
69 | #define A10 10 /* accumulator */ | |||
70 | #define BX11 11 /* (bx) */ | |||
71 | #define CL12 12 /* cl, for shifts */ | |||
72 | #define DX13 13 /* dx, for IO */ | |||
73 | #define SI14 14 /* si */ | |||
74 | #define DI15 15 /* di */ | |||
75 | #define CR16 16 /* control register */ | |||
76 | #define DR17 17 /* debug register */ | |||
77 | #define TR18 18 /* test register */ | |||
78 | #define I19 19 /* immediate, unsigned */ | |||
79 | #define Is20 20 /* immediate, signed */ | |||
80 | #define Ib21 21 /* byte immediate, unsigned */ | |||
81 | #define Ibs22 22 /* byte immediate, signed */ | |||
82 | #define Iw23 23 /* word immediate, unsigned */ | |||
83 | #define Iq24 24 /* quad immediate, unsigned */ | |||
84 | #define O25 25 /* direct address */ | |||
85 | #define Db26 26 /* byte displacement from EIP */ | |||
86 | #define Dl27 27 /* long displacement from EIP */ | |||
87 | #define o128 28 /* constant 1 */ | |||
88 | #define o329 29 /* constant 3 */ | |||
89 | #define OS30 30 /* immediate offset/segment */ | |||
90 | #define ST31 31 /* FP stack top */ | |||
91 | #define STI32 32 /* FP stack */ | |||
92 | #define X33 33 /* extended FP op */ | |||
93 | #define XA34 34 /* for 'fstcw %ax' */ | |||
94 | #define Ril36 36 /* long register in instruction */ | |||
95 | #define Iba37 37 /* byte immediate, don't print if 0xa */ | |||
96 | #define MEx38 38 /* memory, or an extension op */ | |||
97 | ||||
98 | struct inst { | |||
99 | char * i_name; /* name */ | |||
100 | short i_has_modrm; /* has regmodrm byte */ | |||
101 | short i_size; /* operand size */ | |||
102 | int i_mode; /* addressing modes */ | |||
103 | void * i_extra; /* pointer to extra opcode table */ | |||
104 | }; | |||
105 | ||||
106 | #define op1(x)(x) (x) | |||
107 | #define op2(x,y)((x)|((y)<<8)) ((x)|((y)<<8)) | |||
108 | #define op3(x,y,z)((x)|((y)<<8)|((z)<<16)) ((x)|((y)<<8)|((z)<<16)) | |||
109 | ||||
110 | struct finst { | |||
111 | char * f_name; /* name for memory instruction */ | |||
112 | int f_size; /* size for memory instruction */ | |||
113 | int f_rrmode; /* mode for rr instruction */ | |||
114 | void * f_rrname; /* name for rr instruction | |||
115 | (or pointer to table) */ | |||
116 | }; | |||
117 | ||||
118 | char * db_Grp6[] = { | |||
119 | "sldt", "str", "lldt", "ltr", | |||
120 | "verr", "verw", "", "" | |||
121 | }; | |||
122 | ||||
123 | struct inst db_Grp7[] = { | |||
124 | { "sgdt", 0, NONE8, op2(MEx,5)((38)|((5)<<8)), "\0vmcall\0vmlaunch\0vmresume\0vmxoff"}, | |||
125 | { "sidt", 0, NONE8, op2(MEx,4)((38)|((4)<<8)), "monitor\0mwait\0clac\0stac"}, | |||
126 | { "lgdt", 0, NONE8, op2(MEx,7)((38)|((7)<<8)), "xgetbv\0xsetbv\0\0\0vmfunc\0xend\0xtest" }, | |||
127 | { "lidt", 0, NONE8, op1(E)(1), 0 }, | |||
128 | { "smsw", 0, NONE8, op1(E)(1), 0 }, | |||
129 | { "", 0, NONE8, 0, 0 }, | |||
130 | { "lmsw", 0, NONE8, op1(E)(1), 0 }, | |||
131 | { "invlpg", 0, NONE8, op2(MEx,2)((38)|((2)<<8)), "swapgs\0rdtscp" }, | |||
132 | }; | |||
133 | ||||
134 | char * db_Grp8[] = { | |||
135 | "", "", "", "", | |||
136 | "bt", "bts", "btr", "btc" | |||
137 | }; | |||
138 | ||||
139 | struct inst db_Grp9[] = { | |||
140 | { "fxsave", 0, NONE8, op2(MEx,1)((38)|((1)<<8)), "rdfsbase" }, | |||
141 | { "fxrstor", 0, NONE8, op2(MEx,1)((38)|((1)<<8)), "rdgsbase" }, | |||
142 | { "ldmxcsr", 0, NONE8, op2(MEx,1)((38)|((1)<<8)), "wrfsbase" }, | |||
143 | { "stmxcsr", 0, NONE8, op2(MEx,1)((38)|((1)<<8)), "wrgsbase" }, | |||
144 | { "xsave", 0, NONE8, op1(E)(1), 0 }, | |||
145 | { "xrstor", 0, NONE8, op2(MEx,1)((38)|((1)<<8)), "lfence" }, | |||
146 | { "xsaveopt", 0, NONE8, op2(MEx,1)((38)|((1)<<8)), "mfence" }, | |||
147 | { "clflush", 0, NONE8, op2(MEx,1)((38)|((1)<<8)), "sfence" }, | |||
148 | }; | |||
149 | ||||
150 | char * db_GrpA[] = { | |||
151 | "", "cmpxchg8b", "", "", | |||
152 | "", "", "rdrand", "rdseed" | |||
153 | }; | |||
154 | ||||
155 | char * db_GrpB[] = { | |||
156 | "xstore-rng", "xcrypt-ecb", "xcrypt-cbc", "xcrypt-ctr", | |||
157 | "xcrypt-cfb", "xcrypt-ofb", "", "" | |||
158 | }; | |||
159 | ||||
160 | char * db_GrpC[] = { | |||
161 | "montmul", "xsha1", "xsha256", "", | |||
162 | "", "", "", "" | |||
163 | }; | |||
164 | ||||
165 | struct inst db_inst_0f0x[] = { | |||
166 | /*00*/ { NULL((void *)0), 1, NONE8, op1(Ew)(3), db_Grp6 }, | |||
167 | /*01*/ { "", 1, RDEP9, 0, db_Grp7 }, | |||
168 | /*02*/ { "lar", 1, LONG2, op2(E,R)((1)|((5)<<8)), 0 }, | |||
169 | /*03*/ { "lsl", 1, LONG2, op2(E,R)((1)|((5)<<8)), 0 }, | |||
170 | /*04*/ { "", 0, NONE8, 0, 0 }, | |||
171 | /*05*/ { "", 0, NONE8, 0, 0 }, | |||
172 | /*06*/ { "clts", 0, NONE8, 0, 0 }, | |||
173 | /*07*/ { "", 0, NONE8, 0, 0 }, | |||
174 | ||||
175 | /*08*/ { "invd", 0, NONE8, 0, 0 }, | |||
176 | /*09*/ { "wbinvd",0, NONE8, 0, 0 }, | |||
177 | /*0a*/ { "", 0, NONE8, 0, 0 }, | |||
178 | /*0b*/ { "", 0, NONE8, 0, 0 }, | |||
179 | /*0c*/ { "", 0, NONE8, 0, 0 }, | |||
180 | /*0d*/ { "", 0, NONE8, 0, 0 }, | |||
181 | /*0e*/ { "", 0, NONE8, 0, 0 }, | |||
182 | /*0f*/ { "", 0, NONE8, 0, 0 }, | |||
183 | }; | |||
184 | ||||
185 | struct inst db_inst_0f2x[] = { | |||
186 | /*20*/ { "mov", 1, LONG2, op2(CR,E)((16)|((1)<<8)), 0 }, /* use E for reg */ | |||
187 | /*21*/ { "mov", 1, LONG2, op2(DR,E)((17)|((1)<<8)), 0 }, /* since mod == 11 */ | |||
188 | /*22*/ { "mov", 1, LONG2, op2(E,CR)((1)|((16)<<8)), 0 }, | |||
189 | /*23*/ { "mov", 1, LONG2, op2(E,DR)((1)|((17)<<8)), 0 }, | |||
190 | /*24*/ { "mov", 1, LONG2, op2(TR,E)((18)|((1)<<8)), 0 }, | |||
191 | /*25*/ { "", 0, NONE8, 0, 0 }, | |||
192 | /*26*/ { "mov", 1, LONG2, op2(E,TR)((1)|((18)<<8)), 0 }, | |||
193 | /*27*/ { "", 0, NONE8, 0, 0 }, | |||
194 | ||||
195 | /*28*/ { "", 0, NONE8, 0, 0 }, | |||
196 | /*29*/ { "", 0, NONE8, 0, 0 }, | |||
197 | /*2a*/ { "", 0, NONE8, 0, 0 }, | |||
198 | /*2b*/ { "", 0, NONE8, 0, 0 }, | |||
199 | /*2c*/ { "", 0, NONE8, 0, 0 }, | |||
200 | /*2d*/ { "", 0, NONE8, 0, 0 }, | |||
201 | /*2e*/ { "", 0, NONE8, 0, 0 }, | |||
202 | /*2f*/ { "", 0, NONE8, 0, 0 }, | |||
203 | }; | |||
204 | ||||
205 | struct inst db_inst_0f3x[] = { | |||
206 | /*30*/ { "wrmsr", 0, NONE8, 0, 0 }, | |||
207 | /*31*/ { "rdtsc", 0, NONE8, 0, 0 }, | |||
208 | /*32*/ { "rdmsr", 0, NONE8, 0, 0 }, | |||
209 | /*33*/ { "rdpmc", 0, NONE8, 0, 0 }, | |||
210 | /*34*/ { "", 0, NONE8, 0, 0 }, | |||
211 | /*35*/ { "", 0, NONE8, 0, 0 }, | |||
212 | /*36*/ { "", 0, NONE8, 0, 0 }, | |||
213 | /*37*/ { "", 0, NONE8, 0, 0 }, | |||
214 | ||||
215 | /*38*/ { "", 0, NONE8, 0, 0 }, | |||
216 | /*39*/ { "", 0, NONE8, 0, 0 }, | |||
217 | /*3a*/ { "", 0, NONE8, 0, 0 }, | |||
218 | /*3b*/ { "", 0, NONE8, 0, 0 }, | |||
219 | /*3c*/ { "", 0, NONE8, 0, 0 }, | |||
220 | /*3d*/ { "", 0, NONE8, 0, 0 }, | |||
221 | /*3e*/ { "", 0, NONE8, 0, 0 }, | |||
222 | /*3f*/ { "", 0, NONE8, 0, 0 }, | |||
223 | }; | |||
224 | ||||
225 | struct inst db_inst_0f8x[] = { | |||
226 | /*80*/ { "jo", 0, NONE8, op1(Dl)(27), 0 }, | |||
227 | /*81*/ { "jno", 0, NONE8, op1(Dl)(27), 0 }, | |||
228 | /*82*/ { "jb", 0, NONE8, op1(Dl)(27), 0 }, | |||
229 | /*83*/ { "jnb", 0, NONE8, op1(Dl)(27), 0 }, | |||
230 | /*84*/ { "jz", 0, NONE8, op1(Dl)(27), 0 }, | |||
231 | /*85*/ { "jnz", 0, NONE8, op1(Dl)(27), 0 }, | |||
232 | /*86*/ { "jbe", 0, NONE8, op1(Dl)(27), 0 }, | |||
233 | /*87*/ { "jnbe", 0, NONE8, op1(Dl)(27), 0 }, | |||
234 | ||||
235 | /*88*/ { "js", 0, NONE8, op1(Dl)(27), 0 }, | |||
236 | /*89*/ { "jns", 0, NONE8, op1(Dl)(27), 0 }, | |||
237 | /*8a*/ { "jp", 0, NONE8, op1(Dl)(27), 0 }, | |||
238 | /*8b*/ { "jnp", 0, NONE8, op1(Dl)(27), 0 }, | |||
239 | /*8c*/ { "jl", 0, NONE8, op1(Dl)(27), 0 }, | |||
240 | /*8d*/ { "jnl", 0, NONE8, op1(Dl)(27), 0 }, | |||
241 | /*8e*/ { "jle", 0, NONE8, op1(Dl)(27), 0 }, | |||
242 | /*8f*/ { "jnle", 0, NONE8, op1(Dl)(27), 0 }, | |||
243 | }; | |||
244 | ||||
245 | struct inst db_inst_0f9x[] = { | |||
246 | /*90*/ { "seto", 1, NONE8, op1(Eb)(4), 0 }, | |||
247 | /*91*/ { "setno", 1, NONE8, op1(Eb)(4), 0 }, | |||
248 | /*92*/ { "setb", 1, NONE8, op1(Eb)(4), 0 }, | |||
249 | /*93*/ { "setnb", 1, NONE8, op1(Eb)(4), 0 }, | |||
250 | /*94*/ { "setz", 1, NONE8, op1(Eb)(4), 0 }, | |||
251 | /*95*/ { "setnz", 1, NONE8, op1(Eb)(4), 0 }, | |||
252 | /*96*/ { "setbe", 1, NONE8, op1(Eb)(4), 0 }, | |||
253 | /*97*/ { "setnbe",1, NONE8, op1(Eb)(4), 0 }, | |||
254 | ||||
255 | /*98*/ { "sets", 1, NONE8, op1(Eb)(4), 0 }, | |||
256 | /*99*/ { "setns", 1, NONE8, op1(Eb)(4), 0 }, | |||
257 | /*9a*/ { "setp", 1, NONE8, op1(Eb)(4), 0 }, | |||
258 | /*9b*/ { "setnp", 1, NONE8, op1(Eb)(4), 0 }, | |||
259 | /*9c*/ { "setl", 1, NONE8, op1(Eb)(4), 0 }, | |||
260 | /*9d*/ { "setnl", 1, NONE8, op1(Eb)(4), 0 }, | |||
261 | /*9e*/ { "setle", 1, NONE8, op1(Eb)(4), 0 }, | |||
262 | /*9f*/ { "setnle",1, NONE8, op1(Eb)(4), 0 }, | |||
263 | }; | |||
264 | ||||
265 | struct inst db_inst_0fax[] = { | |||
266 | /*a0*/ { "push", 0, QUAD3, op1(Si)(9), 0 }, | |||
267 | /*a1*/ { "pop", 0, QUAD3, op1(Si)(9), 0 }, | |||
268 | /*a2*/ { "cpuid", 0, NONE8, 0, 0 }, | |||
269 | /*a3*/ { "bt", 1, LONG2, op2(R,E)((5)|((1)<<8)), 0 }, | |||
270 | /*a4*/ { "shld", 1, LONG2, op3(Ib,R,E)((21)|((5)<<8)|((1)<<16)), 0 }, | |||
271 | /*a5*/ { "shld", 1, LONG2, op3(CL,R,E)((12)|((5)<<8)|((1)<<16)), 0 }, | |||
272 | /*a6*/ { NULL((void *)0), 1, NONE8, 0, db_GrpC }, | |||
273 | /*a7*/ { NULL((void *)0), 1, NONE8, 0, db_GrpB }, | |||
274 | ||||
275 | /*a8*/ { "push", 0, QUAD3, op1(Si)(9), 0 }, | |||
276 | /*a9*/ { "pop", 0, QUAD3, op1(Si)(9), 0 }, | |||
277 | /*aa*/ { "", 0, NONE8, 0, 0 }, | |||
278 | /*ab*/ { "bts", 1, LONG2, op2(R,E)((5)|((1)<<8)), 0 }, | |||
279 | /*ac*/ { "shrd", 1, LONG2, op3(Ib,E,R)((21)|((1)<<8)|((5)<<16)), 0 }, | |||
280 | /*ad*/ { "shrd", 1, LONG2, op3(CL,E,R)((12)|((1)<<8)|((5)<<16)), 0 }, | |||
281 | /*ae*/ { "", 1, RDEP9, op1(E)(1), db_Grp9 }, | |||
282 | /*af*/ { "imul", 1, LONG2, op2(E,R)((1)|((5)<<8)), 0 }, | |||
283 | }; | |||
284 | ||||
285 | struct inst db_inst_0fbx[] = { | |||
286 | /*b0*/ { "cmpxchg",1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
287 | /*b1*/ { "cmpxchg",1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
288 | /*b2*/ { "lss", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
289 | /*b3*/ { "btr", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
290 | /*b4*/ { "lfs", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
291 | /*b5*/ { "lgs", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
292 | /*b6*/ { "movzb", 1, LONG2, op2(Eb, R)((4)|((5)<<8)), 0 }, | |||
293 | /*b7*/ { "movzw", 1, LONG2, op2(Ew, R)((3)|((5)<<8)), 0 }, | |||
294 | ||||
295 | /*b8*/ { "", 0, NONE8, 0, 0 }, | |||
296 | /*b9*/ { "", 0, NONE8, 0, 0 }, | |||
297 | /*ba*/ { NULL((void *)0), 1, LONG2, op2(Ib, E)((21)|((1)<<8)), db_Grp8 }, | |||
298 | /*bb*/ { "btc", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
299 | /*bc*/ { "bsf", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
300 | /*bd*/ { "bsr", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
301 | /*be*/ { "movsb", 1, LONG2, op2(Eb, R)((4)|((5)<<8)), 0 }, | |||
302 | /*bf*/ { "movsw", 1, LONG2, op2(Ew, R)((3)|((5)<<8)), 0 }, | |||
303 | }; | |||
304 | ||||
305 | struct inst db_inst_0fcx[] = { | |||
306 | /*c0*/ { "xadd", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
307 | /*c1*/ { "xadd", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
308 | /*c2*/ { "", 0, NONE8, 0, 0 }, | |||
309 | /*c3*/ { "", 0, NONE8, 0, 0 }, | |||
310 | /*c4*/ { "", 0, NONE8, 0, 0 }, | |||
311 | /*c5*/ { "", 0, NONE8, 0, 0 }, | |||
312 | /*c6*/ { "", 0, NONE8, 0, 0 }, | |||
313 | /*c7*/ { NULL((void *)0), 1, NONE8, op1(E)(1), db_GrpA }, | |||
314 | ||||
315 | /*c8*/ { "bswap", 0, LONG2, op1(Ril)(36), 0 }, | |||
316 | /*c9*/ { "bswap", 0, LONG2, op1(Ril)(36), 0 }, | |||
317 | /*ca*/ { "bswap", 0, LONG2, op1(Ril)(36), 0 }, | |||
318 | /*cb*/ { "bswap", 0, LONG2, op1(Ril)(36), 0 }, | |||
319 | /*cc*/ { "bswap", 0, LONG2, op1(Ril)(36), 0 }, | |||
320 | /*cd*/ { "bswap", 0, LONG2, op1(Ril)(36), 0 }, | |||
321 | /*ce*/ { "bswap", 0, LONG2, op1(Ril)(36), 0 }, | |||
322 | /*cf*/ { "bswap", 0, LONG2, op1(Ril)(36), 0 }, | |||
323 | }; | |||
324 | ||||
325 | struct inst *db_inst_0f[] = { | |||
326 | db_inst_0f0x, | |||
327 | NULL((void *)0), | |||
328 | db_inst_0f2x, | |||
329 | db_inst_0f3x, | |||
330 | NULL((void *)0), | |||
331 | NULL((void *)0), | |||
332 | NULL((void *)0), | |||
333 | NULL((void *)0), | |||
334 | db_inst_0f8x, | |||
335 | db_inst_0f9x, | |||
336 | db_inst_0fax, | |||
337 | db_inst_0fbx, | |||
338 | db_inst_0fcx, | |||
339 | NULL((void *)0), | |||
340 | NULL((void *)0), | |||
341 | NULL((void *)0) | |||
342 | }; | |||
343 | ||||
344 | char * db_Esc92[] = { | |||
345 | "fnop", "", "", "", | |||
346 | "", "", "", "" | |||
347 | }; | |||
348 | char * db_Esc94[] = { | |||
349 | "fchs", "fabs", "", "", | |||
350 | "ftst", "fxam", "", "" | |||
351 | }; | |||
352 | char * db_Esc95[] = { | |||
353 | "fld1", "fldl2t", "fldl2e", "fldpi", | |||
354 | "fldlg2", "fldln2", "fldz", "" | |||
355 | }; | |||
356 | char * db_Esc96[] = { | |||
357 | "f2xm1", "fyl2x", "fptan", "fpatan", | |||
358 | "fxtract", "fprem1", "fdecstp", "fincstp" | |||
359 | }; | |||
360 | char * db_Esc97[] = { | |||
361 | "fprem", "fyl2xp1", "fsqrt", "fsincos", | |||
362 | "frndint", "fscale", "fsin", "fcos" | |||
363 | }; | |||
364 | ||||
365 | char * db_Esca5[] = { | |||
366 | "", "fucompp", "", "", | |||
367 | "", "", "", "" | |||
368 | }; | |||
369 | ||||
370 | char * db_Escb4[] = { | |||
371 | "fneni", "fndisi", "fnclex", "fninit", | |||
372 | "fsetpm", "", "", "" | |||
373 | }; | |||
374 | ||||
375 | char * db_Esce3[] = { | |||
376 | "", "fcompp", "", "", | |||
377 | "", "", "", "" | |||
378 | }; | |||
379 | ||||
380 | char * db_Escf4[] = { | |||
381 | "fnstsw", "", "", "", | |||
382 | "", "", "", "" | |||
383 | }; | |||
384 | ||||
385 | struct finst db_Esc8[] = { | |||
386 | /*0*/ { "fadd", SNGL4, op2(STI,ST)((32)|((31)<<8)), 0 }, | |||
387 | /*1*/ { "fmul", SNGL4, op2(STI,ST)((32)|((31)<<8)), 0 }, | |||
388 | /*2*/ { "fcom", SNGL4, op2(STI,ST)((32)|((31)<<8)), 0 }, | |||
389 | /*3*/ { "fcomp", SNGL4, op2(STI,ST)((32)|((31)<<8)), 0 }, | |||
390 | /*4*/ { "fsub", SNGL4, op2(STI,ST)((32)|((31)<<8)), 0 }, | |||
391 | /*5*/ { "fsubr", SNGL4, op2(STI,ST)((32)|((31)<<8)), 0 }, | |||
392 | /*6*/ { "fdiv", SNGL4, op2(STI,ST)((32)|((31)<<8)), 0 }, | |||
393 | /*7*/ { "fdivr", SNGL4, op2(STI,ST)((32)|((31)<<8)), 0 }, | |||
394 | }; | |||
395 | ||||
396 | struct finst db_Esc9[] = { | |||
397 | /*0*/ { "fld", SNGL4, op1(STI)(32), 0 }, | |||
398 | /*1*/ { "", NONE8, op1(STI)(32), "fxch" }, | |||
399 | /*2*/ { "fst", SNGL4, op1(X)(33), db_Esc92 }, | |||
400 | /*3*/ { "fstp", SNGL4, op1(X)(33), 0 }, | |||
401 | /*4*/ { "fldenv", NONE8, op1(X)(33), db_Esc94 }, | |||
402 | /*5*/ { "fldcw", NONE8, op1(X)(33), db_Esc95 }, | |||
403 | /*6*/ { "fnstenv",NONE8, op1(X)(33), db_Esc96 }, | |||
404 | /*7*/ { "fnstcw", NONE8, op1(X)(33), db_Esc97 }, | |||
405 | }; | |||
406 | ||||
407 | struct finst db_Esca[] = { | |||
408 | /*0*/ { "fiadd", LONG2, 0, 0 }, | |||
409 | /*1*/ { "fimul", LONG2, 0, 0 }, | |||
410 | /*2*/ { "ficom", LONG2, 0, 0 }, | |||
411 | /*3*/ { "ficomp", LONG2, 0, 0 }, | |||
412 | /*4*/ { "fisub", LONG2, op1(X)(33), 0 }, | |||
413 | /*5*/ { "fisubr", LONG2, 0, 0 }, | |||
414 | /*6*/ { "fidiv", LONG2, 0, 0 }, | |||
415 | /*7*/ { "fidivr", LONG2, 0, 0 } | |||
416 | }; | |||
417 | ||||
418 | struct finst db_Escb[] = { | |||
419 | /*0*/ { "fild", LONG2, 0, 0 }, | |||
420 | /*1*/ { "", NONE8, 0, 0 }, | |||
421 | /*2*/ { "fist", LONG2, 0, 0 }, | |||
422 | /*3*/ { "fistp", LONG2, 0, 0 }, | |||
423 | /*4*/ { "", WORD1, op1(X)(33), db_Escb4 }, | |||
424 | /*5*/ { "fld", EXTR6, 0, 0 }, | |||
425 | /*6*/ { "", WORD1, 0, 0 }, | |||
426 | /*7*/ { "fstp", EXTR6, 0, 0 }, | |||
427 | }; | |||
428 | ||||
429 | struct finst db_Escc[] = { | |||
430 | /*0*/ { "fadd", DBLR5, op2(ST,STI)((31)|((32)<<8)), 0 }, | |||
431 | /*1*/ { "fmul", DBLR5, op2(ST,STI)((31)|((32)<<8)), 0 }, | |||
432 | /*2*/ { "fcom", DBLR5, 0, 0 }, | |||
433 | /*3*/ { "fcomp", DBLR5, 0, 0 }, | |||
434 | /*4*/ { "fsub", DBLR5, op2(ST,STI)((31)|((32)<<8)), "fsubr" }, | |||
435 | /*5*/ { "fsubr", DBLR5, op2(ST,STI)((31)|((32)<<8)), "fsub" }, | |||
436 | /*6*/ { "fdiv", DBLR5, op2(ST,STI)((31)|((32)<<8)), "fdivr" }, | |||
437 | /*7*/ { "fdivr", DBLR5, op2(ST,STI)((31)|((32)<<8)), "fdiv" }, | |||
438 | }; | |||
439 | ||||
440 | struct finst db_Escd[] = { | |||
441 | /*0*/ { "fld", DBLR5, op1(STI)(32), "ffree" }, | |||
442 | /*1*/ { "", NONE8, 0, 0 }, | |||
443 | /*2*/ { "fst", DBLR5, op1(STI)(32), 0 }, | |||
444 | /*3*/ { "fstp", DBLR5, op1(STI)(32), 0 }, | |||
445 | /*4*/ { "frstor", NONE8, op1(STI)(32), "fucom" }, | |||
446 | /*5*/ { "", NONE8, op1(STI)(32), "fucomp" }, | |||
447 | /*6*/ { "fnsave", NONE8, 0, 0 }, | |||
448 | /*7*/ { "fnstsw", NONE8, 0, 0 }, | |||
449 | }; | |||
450 | ||||
451 | struct finst db_Esce[] = { | |||
452 | /*0*/ { "fiadd", WORD1, op2(ST,STI)((31)|((32)<<8)), "faddp" }, | |||
453 | /*1*/ { "fimul", WORD1, op2(ST,STI)((31)|((32)<<8)), "fmulp" }, | |||
454 | /*2*/ { "ficom", WORD1, 0, 0 }, | |||
455 | /*3*/ { "ficomp", WORD1, op1(X)(33), db_Esce3 }, | |||
456 | /*4*/ { "fisub", WORD1, op2(ST,STI)((31)|((32)<<8)), "fsubrp" }, | |||
457 | /*5*/ { "fisubr", WORD1, op2(ST,STI)((31)|((32)<<8)), "fsubp" }, | |||
458 | /*6*/ { "fidiv", WORD1, op2(ST,STI)((31)|((32)<<8)), "fdivrp" }, | |||
459 | /*7*/ { "fidivr", WORD1, op2(ST,STI)((31)|((32)<<8)), "fdivp" }, | |||
460 | }; | |||
461 | ||||
462 | struct finst db_Escf[] = { | |||
463 | /*0*/ { "fild", WORD1, 0, 0 }, | |||
464 | /*1*/ { "", WORD1, 0, 0 }, | |||
465 | /*2*/ { "fist", WORD1, 0, 0 }, | |||
466 | /*3*/ { "fistp", WORD1, 0, 0 }, | |||
467 | /*4*/ { "fbld", NONE8, op1(XA)(34), db_Escf4 }, | |||
468 | /*5*/ { "fild", QUAD3, 0, 0 }, | |||
469 | /*6*/ { "fbstp", NONE8, 0, 0 }, | |||
470 | /*7*/ { "fistp", QUAD3, 0, 0 }, | |||
471 | }; | |||
472 | ||||
473 | struct finst *db_Esc_inst[] = { | |||
474 | db_Esc8, db_Esc9, db_Esca, db_Escb, | |||
475 | db_Escc, db_Escd, db_Esce, db_Escf | |||
476 | }; | |||
477 | ||||
478 | char * db_Grp1[] = { | |||
479 | "add", | |||
480 | "or", | |||
481 | "adc", | |||
482 | "sbb", | |||
483 | "and", | |||
484 | "sub", | |||
485 | "xor", | |||
486 | "cmp" | |||
487 | }; | |||
488 | ||||
489 | char * db_Grp2[] = { | |||
490 | "rol", | |||
491 | "ror", | |||
492 | "rcl", | |||
493 | "rcr", | |||
494 | "shl", | |||
495 | "shr", | |||
496 | "shl", | |||
497 | "sar" | |||
498 | }; | |||
499 | ||||
500 | struct inst db_Grp3[] = { | |||
501 | { "test", 1, NONE8, op2(I,E)((19)|((1)<<8)), 0 }, | |||
502 | { "test", 1, NONE8, op2(I,E)((19)|((1)<<8)), 0 }, | |||
503 | { "not", 1, NONE8, op1(E)(1), 0 }, | |||
504 | { "neg", 1, NONE8, op1(E)(1), 0 }, | |||
505 | { "mul", 1, NONE8, op2(E,A)((1)|((10)<<8)), 0 }, | |||
506 | { "imul", 1, NONE8, op2(E,A)((1)|((10)<<8)), 0 }, | |||
507 | { "div", 1, NONE8, op2(E,A)((1)|((10)<<8)), 0 }, | |||
508 | { "idiv", 1, NONE8, op2(E,A)((1)|((10)<<8)), 0 }, | |||
509 | }; | |||
510 | ||||
511 | struct inst db_Grp4[] = { | |||
512 | { "inc", 1, BYTE0, op1(E)(1), 0 }, | |||
513 | { "dec", 1, BYTE0, op1(E)(1), 0 }, | |||
514 | { "", 1, NONE8, 0, 0 }, | |||
515 | { "", 1, NONE8, 0, 0 }, | |||
516 | { "", 1, NONE8, 0, 0 }, | |||
517 | { "", 1, NONE8, 0, 0 }, | |||
518 | { "", 1, NONE8, 0, 0 }, | |||
519 | { "", 1, NONE8, 0, 0 } | |||
520 | }; | |||
521 | ||||
522 | struct inst db_Grp5[] = { | |||
523 | { "inc", 1, LONG2, op1(E)(1), 0 }, | |||
524 | { "dec", 1, LONG2, op1(E)(1), 0 }, | |||
525 | { "call", 1, QUAD3, op1(Eind)(2),0 }, | |||
526 | { "lcall", 1, NONE8, op1(Eind)(2),0 }, | |||
527 | { "jmp", 1, NONE8, op1(Eind)(2),0 }, | |||
528 | { "ljmp", 1, NONE8, op1(Eind)(2),0 }, | |||
529 | { "push", 1, QUAD3, op1(E)(1), 0 }, | |||
530 | { "", 1, NONE8, 0, 0 } | |||
531 | }; | |||
532 | ||||
533 | struct inst db_inst_table[256] = { | |||
534 | /*00*/ { "add", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
535 | /*01*/ { "add", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
536 | /*02*/ { "add", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
537 | /*03*/ { "add", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
538 | /*04*/ { "add", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
539 | /*05*/ { "add", 0, LONG2, op2(Is, A)((20)|((10)<<8)), 0 }, | |||
540 | /*06*/ { "", 0, NONE8, op1(Si)(9), 0 }, | |||
541 | /*07*/ { "", 0, NONE8, op1(Si)(9), 0 }, | |||
542 | ||||
543 | /*08*/ { "or", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
544 | /*09*/ { "or", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
545 | /*0a*/ { "or", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
546 | /*0b*/ { "or", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
547 | /*0c*/ { "or", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
548 | /*0d*/ { "or", 0, LONG2, op2(I, A)((19)|((10)<<8)), 0 }, | |||
549 | /*0e*/ { "", 0, NONE8, op1(Si)(9), 0 }, | |||
550 | /*0f*/ { "", 0, NONE8, 0, 0 }, | |||
551 | ||||
552 | /*10*/ { "adc", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
553 | /*11*/ { "adc", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
554 | /*12*/ { "adc", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
555 | /*13*/ { "adc", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
556 | /*14*/ { "adc", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
557 | /*15*/ { "adc", 0, LONG2, op2(Is, A)((20)|((10)<<8)), 0 }, | |||
558 | /*16*/ { "", 0, NONE8, op1(Si)(9), 0 }, | |||
559 | /*17*/ { "", 0, NONE8, op1(Si)(9), 0 }, | |||
560 | ||||
561 | /*18*/ { "sbb", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
562 | /*19*/ { "sbb", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
563 | /*1a*/ { "sbb", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
564 | /*1b*/ { "sbb", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
565 | /*1c*/ { "sbb", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
566 | /*1d*/ { "sbb", 0, LONG2, op2(Is, A)((20)|((10)<<8)), 0 }, | |||
567 | /*1e*/ { "", 0, NONE8, op1(Si)(9), 0 }, | |||
568 | /*1f*/ { "", 0, NONE8, op1(Si)(9), 0 }, | |||
569 | ||||
570 | /*20*/ { "and", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
571 | /*21*/ { "and", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
572 | /*22*/ { "and", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
573 | /*23*/ { "and", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
574 | /*24*/ { "and", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
575 | /*25*/ { "and", 0, LONG2, op2(I, A)((19)|((10)<<8)), 0 }, | |||
576 | /*26*/ { "", 0, NONE8, 0, 0 }, | |||
577 | /*27*/ { "", 0, NONE8, 0, 0 }, | |||
578 | ||||
579 | /*28*/ { "sub", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
580 | /*29*/ { "sub", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
581 | /*2a*/ { "sub", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
582 | /*2b*/ { "sub", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
583 | /*2c*/ { "sub", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
584 | /*2d*/ { "sub", 0, LONG2, op2(Is, A)((20)|((10)<<8)), 0 }, | |||
585 | /*2e*/ { "", 0, NONE8, 0, 0 }, | |||
586 | /*2f*/ { "", 0, NONE8, 0, 0 }, | |||
587 | ||||
588 | /*30*/ { "xor", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
589 | /*31*/ { "xor", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
590 | /*32*/ { "xor", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
591 | /*33*/ { "xor", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
592 | /*34*/ { "xor", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
593 | /*35*/ { "xor", 0, LONG2, op2(I, A)((19)|((10)<<8)), 0 }, | |||
594 | /*36*/ { "", 0, NONE8, 0, 0 }, | |||
595 | /*37*/ { "", 0, NONE8, 0, 0 }, | |||
596 | ||||
597 | /*38*/ { "cmp", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
598 | /*39*/ { "cmp", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
599 | /*3a*/ { "cmp", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
600 | /*3b*/ { "cmp", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
601 | /*3c*/ { "cmp", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
602 | /*3d*/ { "cmp", 0, LONG2, op2(Is, A)((20)|((10)<<8)), 0 }, | |||
603 | /*3e*/ { "", 0, NONE8, 0, 0 }, | |||
604 | /*3f*/ { "", 0, NONE8, 0, 0 }, | |||
605 | ||||
606 | /*40*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
607 | /*41*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
608 | /*42*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
609 | /*43*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
610 | /*44*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
611 | /*45*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
612 | /*46*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
613 | /*47*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
614 | ||||
615 | /*48*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
616 | /*49*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
617 | /*4a*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
618 | /*4b*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
619 | /*4c*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
620 | /*4d*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
621 | /*4e*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
622 | /*4f*/ { "", 0, LONG2, op1(Ri)(7), 0 }, | |||
623 | ||||
624 | /*50*/ { "push", 0, QUAD3, op1(Ri)(7), 0 }, | |||
625 | /*51*/ { "push", 0, QUAD3, op1(Ri)(7), 0 }, | |||
626 | /*52*/ { "push", 0, QUAD3, op1(Ri)(7), 0 }, | |||
627 | /*53*/ { "push", 0, QUAD3, op1(Ri)(7), 0 }, | |||
628 | /*54*/ { "push", 0, QUAD3, op1(Ri)(7), 0 }, | |||
629 | /*55*/ { "push", 0, QUAD3, op1(Ri)(7), 0 }, | |||
630 | /*56*/ { "push", 0, QUAD3, op1(Ri)(7), 0 }, | |||
631 | /*57*/ { "push", 0, QUAD3, op1(Ri)(7), 0 }, | |||
632 | ||||
633 | /*58*/ { "pop", 0, QUAD3, op1(Ri)(7), 0 }, | |||
634 | /*59*/ { "pop", 0, QUAD3, op1(Ri)(7), 0 }, | |||
635 | /*5a*/ { "pop", 0, QUAD3, op1(Ri)(7), 0 }, | |||
636 | /*5b*/ { "pop", 0, QUAD3, op1(Ri)(7), 0 }, | |||
637 | /*5c*/ { "pop", 0, QUAD3, op1(Ri)(7), 0 }, | |||
638 | /*5d*/ { "pop", 0, QUAD3, op1(Ri)(7), 0 }, | |||
639 | /*5e*/ { "pop", 0, QUAD3, op1(Ri)(7), 0 }, | |||
640 | /*5f*/ { "pop", 0, QUAD3, op1(Ri)(7), 0 }, | |||
641 | ||||
642 | /*60*/ { "", 0, LONG2, 0, 0 }, | |||
643 | /*61*/ { "", 0, LONG2, 0, 0 }, | |||
644 | /*62*/ { "", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
645 | /*63*/ { "movsxd",1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
646 | /*64*/ { "", 0, NONE8, 0, 0 }, | |||
647 | /*65*/ { "", 0, NONE8, 0, 0 }, | |||
648 | /*66*/ { "", 0, NONE8, 0, 0 }, | |||
649 | /*67*/ { "", 0, NONE8, 0, 0 }, | |||
650 | ||||
651 | /*68*/ { "push", 0, QUAD3, op1(I)(19), 0 }, | |||
652 | /*69*/ { "imul", 1, LONG2, op3(I,E,R)((19)|((1)<<8)|((5)<<16)), 0 }, | |||
653 | /*6a*/ { "push", 0, QUAD3, op1(Ibs)(22), 0 }, | |||
654 | /*6b*/ { "imul", 1, LONG2, op3(Ibs,E,R)((22)|((1)<<8)|((5)<<16)),0 }, | |||
655 | /*6c*/ { "ins", 0, BYTE0, op2(DX, DI)((13)|((15)<<8)), 0 }, | |||
656 | /*6d*/ { "ins", 0, LONG2, op2(DX, DI)((13)|((15)<<8)), 0 }, | |||
657 | /*6e*/ { "outs", 0, BYTE0, op2(SI, DX)((14)|((13)<<8)), 0 }, | |||
658 | /*6f*/ { "outs", 0, LONG2, op2(SI, DX)((14)|((13)<<8)), 0 }, | |||
659 | ||||
660 | /*70*/ { "jo", 0, NONE8, op1(Db)(26), 0 }, | |||
661 | /*71*/ { "jno", 0, NONE8, op1(Db)(26), 0 }, | |||
662 | /*72*/ { "jb", 0, NONE8, op1(Db)(26), 0 }, | |||
663 | /*73*/ { "jnb", 0, NONE8, op1(Db)(26), 0 }, | |||
664 | /*74*/ { "jz", 0, NONE8, op1(Db)(26), 0 }, | |||
665 | /*75*/ { "jnz", 0, NONE8, op1(Db)(26), 0 }, | |||
666 | /*76*/ { "jbe", 0, NONE8, op1(Db)(26), 0 }, | |||
667 | /*77*/ { "jnbe", 0, NONE8, op1(Db)(26), 0 }, | |||
668 | ||||
669 | /*78*/ { "js", 0, NONE8, op1(Db)(26), 0 }, | |||
670 | /*79*/ { "jns", 0, NONE8, op1(Db)(26), 0 }, | |||
671 | /*7a*/ { "jp", 0, NONE8, op1(Db)(26), 0 }, | |||
672 | /*7b*/ { "jnp", 0, NONE8, op1(Db)(26), 0 }, | |||
673 | /*7c*/ { "jl", 0, NONE8, op1(Db)(26), 0 }, | |||
674 | /*7d*/ { "jnl", 0, NONE8, op1(Db)(26), 0 }, | |||
675 | /*7e*/ { "jle", 0, NONE8, op1(Db)(26), 0 }, | |||
676 | /*7f*/ { "jnle", 0, NONE8, op1(Db)(26), 0 }, | |||
677 | ||||
678 | /*80*/ { NULL((void *)0), 1, BYTE0, op2(I, E)((19)|((1)<<8)), db_Grp1 }, | |||
679 | /*81*/ { NULL((void *)0), 1, LONG2, op2(I, E)((19)|((1)<<8)), db_Grp1 }, | |||
680 | /*82*/ { NULL((void *)0), 1, BYTE0, op2(I, E)((19)|((1)<<8)), db_Grp1 }, | |||
681 | /*83*/ { NULL((void *)0), 1, LONG2, op2(Ibs,E)((22)|((1)<<8)), db_Grp1 }, | |||
682 | /*84*/ { "test", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
683 | /*85*/ { "test", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
684 | /*86*/ { "xchg", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
685 | /*87*/ { "xchg", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
686 | ||||
687 | /*88*/ { "mov", 1, BYTE0, op2(R, E)((5)|((1)<<8)), 0 }, | |||
688 | /*89*/ { "mov", 1, LONG2, op2(R, E)((5)|((1)<<8)), 0 }, | |||
689 | /*8a*/ { "mov", 1, BYTE0, op2(E, R)((1)|((5)<<8)), 0 }, | |||
690 | /*8b*/ { "mov", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
691 | /*8c*/ { "mov", 1, NONE8, op2(S, Ew)((8)|((3)<<8)), 0 }, | |||
692 | /*8d*/ { "lea", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
693 | /*8e*/ { "mov", 1, NONE8, op2(Ew, S)((3)|((8)<<8)), 0 }, | |||
694 | /*8f*/ { "pop", 1, QUAD3, op1(Dl)(27), 0 }, | |||
695 | ||||
696 | /*90*/ { "nop", 0, NONE8, 0, 0 }, | |||
697 | /*91*/ { "xchg", 0, LONG2, op2(A, Ri)((10)|((7)<<8)), 0 }, | |||
698 | /*92*/ { "xchg", 0, LONG2, op2(A, Ri)((10)|((7)<<8)), 0 }, | |||
699 | /*93*/ { "xchg", 0, LONG2, op2(A, Ri)((10)|((7)<<8)), 0 }, | |||
700 | /*94*/ { "xchg", 0, LONG2, op2(A, Ri)((10)|((7)<<8)), 0 }, | |||
701 | /*95*/ { "xchg", 0, LONG2, op2(A, Ri)((10)|((7)<<8)), 0 }, | |||
702 | /*96*/ { "xchg", 0, LONG2, op2(A, Ri)((10)|((7)<<8)), 0 }, | |||
703 | /*97*/ { "xchg", 0, LONG2, op2(A, Ri)((10)|((7)<<8)), 0 }, | |||
704 | ||||
705 | /*98*/ { "cbw", 0, SDEP7, 0, "cwde\0cdqe" }, | |||
706 | /*99*/ { "cwd", 0, SDEP7, 0, "cdq\0cqo" }, | |||
707 | /*9a*/ { "", 0, NONE8, op1(OS)(30), 0 }, | |||
708 | /*9b*/ { "wait", 0, NONE8, 0, 0 }, | |||
709 | /*9c*/ { "pushf", 0, QUAD3, 0, 0 }, | |||
710 | /*9d*/ { "popf", 0, QUAD3, 0, 0 }, | |||
711 | /*9e*/ { "sahf", 0, NONE8, 0, 0 }, | |||
712 | /*9f*/ { "lahf", 0, NONE8, 0, 0 }, | |||
713 | ||||
714 | /*a0*/ { "mov", 0, BYTE0, op2(O, A)((25)|((10)<<8)), 0 }, | |||
715 | /*a1*/ { "mov", 0, LONG2, op2(O, A)((25)|((10)<<8)), 0 }, | |||
716 | /*a2*/ { "mov", 0, BYTE0, op2(A, O)((10)|((25)<<8)), 0 }, | |||
717 | /*a3*/ { "mov", 0, LONG2, op2(A, O)((10)|((25)<<8)), 0 }, | |||
718 | /*a4*/ { "movs", 0, BYTE0, op2(SI,DI)((14)|((15)<<8)), 0 }, | |||
719 | /*a5*/ { "movs", 0, LONG2, op2(SI,DI)((14)|((15)<<8)), 0 }, | |||
720 | /*a6*/ { "cmps", 0, BYTE0, op2(SI,DI)((14)|((15)<<8)), 0 }, | |||
721 | /*a7*/ { "cmps", 0, LONG2, op2(SI,DI)((14)|((15)<<8)), 0 }, | |||
722 | ||||
723 | /*a8*/ { "test", 0, BYTE0, op2(I, A)((19)|((10)<<8)), 0 }, | |||
724 | /*a9*/ { "test", 0, LONG2, op2(I, A)((19)|((10)<<8)), 0 }, | |||
725 | /*aa*/ { "stos", 0, BYTE0, op1(DI)(15), 0 }, | |||
726 | /*ab*/ { "stos", 0, LONG2, op1(DI)(15), 0 }, | |||
727 | /*ac*/ { "lods", 0, BYTE0, op1(SI)(14), 0 }, | |||
728 | /*ad*/ { "lods", 0, LONG2, op1(SI)(14), 0 }, | |||
729 | /*ae*/ { "scas", 0, BYTE0, op1(SI)(14), 0 }, | |||
730 | /*af*/ { "scas", 0, LONG2, op1(SI)(14), 0 }, | |||
731 | ||||
732 | /*b0*/ { "mov", 0, BYTE0, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
733 | /*b1*/ { "mov", 0, BYTE0, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
734 | /*b2*/ { "mov", 0, BYTE0, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
735 | /*b3*/ { "mov", 0, BYTE0, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
736 | /*b4*/ { "mov", 0, BYTE0, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
737 | /*b5*/ { "mov", 0, BYTE0, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
738 | /*b6*/ { "mov", 0, BYTE0, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
739 | /*b7*/ { "mov", 0, BYTE0, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
740 | ||||
741 | /*b8*/ { "mov", 0, LONG2, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
742 | /*b9*/ { "mov", 0, LONG2, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
743 | /*ba*/ { "mov", 0, LONG2, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
744 | /*bb*/ { "mov", 0, LONG2, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
745 | /*bc*/ { "mov", 0, LONG2, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
746 | /*bd*/ { "mov", 0, LONG2, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
747 | /*be*/ { "mov", 0, LONG2, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
748 | /*bf*/ { "mov", 0, LONG2, op2(I, Ri)((19)|((7)<<8)), 0 }, | |||
749 | ||||
750 | /*c0*/ { NULL((void *)0), 1, BYTE0, op2(Ib, E)((21)|((1)<<8)), db_Grp2 }, | |||
751 | /*c1*/ { NULL((void *)0), 1, LONG2, op2(Ib, E)((21)|((1)<<8)), db_Grp2 }, | |||
752 | /*c2*/ { "ret", 0, NONE8, op1(Iw)(23), 0 }, | |||
753 | /*c3*/ { "ret", 0, NONE8, 0, 0 }, | |||
754 | /*c4*/ { "", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
755 | /*c5*/ { "", 1, LONG2, op2(E, R)((1)|((5)<<8)), 0 }, | |||
756 | /*c6*/ { "mov", 1, BYTE0, op2(I, E)((19)|((1)<<8)), 0 }, | |||
757 | /*c7*/ { "mov", 1, LONG2, op2(I, E)((19)|((1)<<8)), 0 }, | |||
758 | ||||
759 | /*c8*/ { "enter", 0, NONE8, op2(Iq, Ib)((24)|((21)<<8)), 0 }, | |||
760 | /*c9*/ { "leave", 0, NONE8, 0, 0 }, | |||
761 | /*ca*/ { "lret", 0, NONE8, op1(Iw)(23), 0 }, | |||
762 | /*cb*/ { "lret", 0, NONE8, 0, 0 }, | |||
763 | /*cc*/ { "int", 0, NONE8, op1(o3)(29), 0 }, | |||
764 | /*cd*/ { "int", 0, NONE8, op1(Ib)(21), 0 }, | |||
765 | /*ce*/ { "", 0, NONE8, 0, 0 }, | |||
766 | /*cf*/ { "iret", 0, NONE8, 0, 0 }, | |||
767 | ||||
768 | /*d0*/ { NULL((void *)0), 1, BYTE0, op2(o1, E)((28)|((1)<<8)), db_Grp2 }, | |||
769 | /*d1*/ { NULL((void *)0), 1, LONG2, op2(o1, E)((28)|((1)<<8)), db_Grp2 }, | |||
770 | /*d2*/ { NULL((void *)0), 1, BYTE0, op2(CL, E)((12)|((1)<<8)), db_Grp2 }, | |||
771 | /*d3*/ { NULL((void *)0), 1, LONG2, op2(CL, E)((12)|((1)<<8)), db_Grp2 }, | |||
772 | /*d4*/ { "", 1, NONE8, op1(Iba)(37), 0 }, | |||
773 | /*d5*/ { "", 1, NONE8, op1(Iba)(37), 0 }, | |||
774 | /*d6*/ { ".byte\t0xd6",0, NONE8, 0, 0 }, | |||
775 | /*d7*/ { "xlat", 0, BYTE0, op1(BX)(11), 0 }, | |||
776 | ||||
777 | /* d8 to df block is ignored: direct test in code handles them */ | |||
778 | /*d8*/ { "", 1, NONE8, 0, db_Esc8 }, | |||
779 | /*d9*/ { "", 1, NONE8, 0, db_Esc9 }, | |||
780 | /*da*/ { "", 1, NONE8, 0, db_Esca }, | |||
781 | /*db*/ { "", 1, NONE8, 0, db_Escb }, | |||
782 | /*dc*/ { "", 1, NONE8, 0, db_Escc }, | |||
783 | /*dd*/ { "", 1, NONE8, 0, db_Escd }, | |||
784 | /*de*/ { "", 1, NONE8, 0, db_Esce }, | |||
785 | /*df*/ { "", 1, NONE8, 0, db_Escf }, | |||
786 | ||||
787 | /*e0*/ { "loopne",0, NONE8, op1(Db)(26), 0 }, | |||
788 | /*e1*/ { "loope", 0, NONE8, op1(Db)(26), 0 }, | |||
789 | /*e2*/ { "loop", 0, NONE8, op1(Db)(26), 0 }, | |||
790 | /*e3*/ { "jcxz", 0, SDEP7, op1(Db)(26), "jecxz\0jrcxz" }, | |||
791 | /*e4*/ { "in", 0, BYTE0, op2(Ib, A)((21)|((10)<<8)), 0 }, | |||
792 | /*e5*/ { "in", 0, LONG2, op2(Ib, A)((21)|((10)<<8)) , 0 }, | |||
793 | /*e6*/ { "out", 0, BYTE0, op2(A, Ib)((10)|((21)<<8)), 0 }, | |||
794 | /*e7*/ { "out", 0, LONG2, op2(A, Ib)((10)|((21)<<8)) , 0 }, | |||
795 | ||||
796 | /*e8*/ { "call", 0, QUAD3, op1(Dl)(27), 0 }, | |||
797 | /*e9*/ { "jmp", 0, NONE8, op1(Dl)(27), 0 }, | |||
798 | /*ea*/ { "", 0, NONE8, op1(OS)(30), 0 }, | |||
799 | /*eb*/ { "jmp", 0, NONE8, op1(Db)(26), 0 }, | |||
800 | /*ec*/ { "in", 0, BYTE0, op2(DX, A)((13)|((10)<<8)), 0 }, | |||
801 | /*ed*/ { "in", 0, LONG2, op2(DX, A)((13)|((10)<<8)) , 0 }, | |||
802 | /*ee*/ { "out", 0, BYTE0, op2(A, DX)((10)|((13)<<8)), 0 }, | |||
803 | /*ef*/ { "out", 0, LONG2, op2(A, DX)((10)|((13)<<8)) , 0 }, | |||
804 | ||||
805 | /*f0*/ { "", 0, NONE8, 0, 0 }, | |||
806 | /*f1*/ { "", 0, NONE8, 0, 0 }, | |||
807 | /*f2*/ { "", 0, NONE8, 0, 0 }, | |||
808 | /*f3*/ { "", 0, NONE8, 0, 0 }, | |||
809 | /*f4*/ { "hlt", 0, NONE8, 0, 0 }, | |||
810 | /*f5*/ { "cmc", 0, NONE8, 0, 0 }, | |||
811 | /*f6*/ { "", 1, BYTE0, 0, db_Grp3 }, | |||
812 | /*f7*/ { "", 1, LONG2, 0, db_Grp3 }, | |||
813 | ||||
814 | /*f8*/ { "clc", 0, NONE8, 0, 0 }, | |||
815 | /*f9*/ { "stc", 0, NONE8, 0, 0 }, | |||
816 | /*fa*/ { "cli", 0, NONE8, 0, 0 }, | |||
817 | /*fb*/ { "sti", 0, NONE8, 0, 0 }, | |||
818 | /*fc*/ { "cld", 0, NONE8, 0, 0 }, | |||
819 | /*fd*/ { "std", 0, NONE8, 0, 0 }, | |||
820 | /*fe*/ { "", 1, RDEP9, 0, db_Grp4 }, | |||
821 | /*ff*/ { "", 1, RDEP9, 0, db_Grp5 }, | |||
822 | }; | |||
823 | ||||
824 | struct inst db_bad_inst = | |||
825 | { "???", 0, NONE8, 0, 0 } | |||
826 | ; | |||
827 | ||||
828 | #define REX_W(rex)(((rex) & 0x8) == 0x8) (((rex) & 0x8) == 0x8) /* 64-bit operand size */ | |||
829 | #define REX_R(rex)(((rex) & 0x4) << 1) (((rex) & 0x4) << 1) /* ModRM reg field extension */ | |||
830 | #define REX_X(rex)(((rex) & 0x2) << 2) (((rex) & 0x2) << 2) /* SIB index field extension */ | |||
831 | #define REX_B(rex)(((rex) & 0x1) << 3) (((rex) & 0x1) << 3) /* ModRM r/m and SIB base ext */ | |||
832 | ||||
833 | #define f_mod(byte)((byte)>>6) ((byte)>>6) | |||
834 | #define f_reg(byte, rex)((((byte)>>3)&0x7) + (((rex) & 0x4) << 1) ) ((((byte)>>3)&0x7) + REX_R(rex)(((rex) & 0x4) << 1)) | |||
835 | #define f_rm(byte, rex)(((byte)&0x7) + (((rex) & 0x1) << 3)) (((byte)&0x7) + REX_B(rex)(((rex) & 0x1) << 3)) | |||
836 | ||||
837 | #define sib_ss(byte)((byte)>>6) ((byte)>>6) | |||
838 | #define sib_index(byte, rex)((((byte)>>3)&0x7) + (((rex) & 0x2) << 2) ) ((((byte)>>3)&0x7) + REX_X(rex)(((rex) & 0x2) << 2)) | |||
839 | #define sib_base(byte, rex)(((byte)&0x7) + (((rex) & 0x1) << 3)) (((byte)&0x7) + REX_B(rex)(((rex) & 0x1) << 3)) | |||
840 | ||||
841 | struct i_addr { | |||
842 | int is_reg; /* if reg, reg number is in 'disp' */ | |||
843 | int disp; | |||
844 | char * base; | |||
845 | char * index; | |||
846 | int ss; | |||
847 | }; | |||
848 | ||||
849 | char * db_index_reg_16[8] = { | |||
850 | "%bx,%si", | |||
851 | "%bx,%di", | |||
852 | "%bp,%si", | |||
853 | "%bp,%di", | |||
854 | "%si", | |||
855 | "%di", | |||
856 | "%bp", | |||
857 | "%bx" | |||
858 | }; | |||
859 | ||||
860 | char * db_reg[4][16] = { | |||
861 | { "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", | |||
862 | "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"}, | |||
863 | { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", | |||
864 | "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"}, | |||
865 | { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", | |||
866 | "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"}, | |||
867 | { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", | |||
868 | "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" } | |||
869 | }; | |||
870 | ||||
871 | char * db_seg_reg[8] = { | |||
872 | "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", "" | |||
873 | }; | |||
874 | ||||
875 | /* | |||
876 | * lengths for size attributes | |||
877 | */ | |||
878 | int db_lengths[] = { | |||
879 | 1, /* BYTE */ | |||
880 | 2, /* WORD */ | |||
881 | 4, /* LONG */ | |||
882 | 8, /* QUAD */ | |||
883 | 4, /* SNGL */ | |||
884 | 8, /* DBLR */ | |||
885 | 10, /* EXTR */ | |||
886 | }; | |||
887 | ||||
888 | #define get_value_inc(result, loc, size, is_signed)do { result = db_get_value((loc), (size), (is_signed)); (loc) += (size); } while (0) \ | |||
889 | do { \ | |||
890 | result = db_get_value((loc), (size), (is_signed)); \ | |||
891 | (loc) += (size); \ | |||
892 | } while (0) | |||
893 | ||||
894 | ||||
895 | vaddr_t db_read_address(vaddr_t, int, int, int, struct i_addr *); | |||
896 | void db_print_address(char *, int, struct i_addr *); | |||
897 | vaddr_t db_disasm_esc(vaddr_t, int, int, int, int, char *); | |||
898 | vaddr_t db_disasm_3dnow(vaddr_t, int, int, int, char *); | |||
899 | ||||
900 | /* | |||
901 | * Read address at location and return updated location. | |||
902 | */ | |||
903 | vaddr_t | |||
904 | db_read_address(vaddr_t loc, int short_addr, int regmodrm, int rex, | |||
905 | struct i_addr *addrp) | |||
906 | { | |||
907 | int mod, rm, sib, index, disp, size; | |||
908 | ||||
909 | size = (short_addr ? LONG2 : QUAD3); | |||
910 | mod = f_mod(regmodrm)((regmodrm)>>6); | |||
911 | rm = f_rm(regmodrm, rex)(((regmodrm)&0x7) + (((rex) & 0x1) << 3)); | |||
912 | ||||
913 | if (mod == 3) { | |||
914 | addrp->is_reg = 1; | |||
915 | addrp->disp = rm; | |||
916 | return (loc); | |||
917 | } | |||
918 | addrp->is_reg = 0; | |||
919 | addrp->index = 0; | |||
920 | ||||
921 | if (rm == 4 || rm == 12) { | |||
922 | get_value_inc(sib, loc, 1, 0)do { sib = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
923 | rm = sib_base(sib, rex)(((sib)&0x7) + (((rex) & 0x1) << 3)); | |||
924 | index = sib_index(sib, rex)((((sib)>>3)&0x7) + (((rex) & 0x2) << 2)); | |||
925 | if (index != 4) | |||
926 | addrp->index = db_reg[size][index]; | |||
927 | addrp->ss = sib_ss(sib)((sib)>>6); | |||
928 | } | |||
929 | ||||
930 | switch (mod) { | |||
931 | case 0: | |||
932 | if (rm == 5) { | |||
933 | get_value_inc(addrp->disp, loc, 4, 0)do { addrp->disp = db_get_value((loc), (4), (0)); (loc) += (4); } while (0); | |||
934 | addrp->base = 0; | |||
935 | } else { | |||
936 | addrp->disp = 0; | |||
937 | addrp->base = db_reg[size][rm]; | |||
938 | } | |||
939 | break; | |||
940 | case 1: | |||
941 | get_value_inc(disp, loc, 1, 1)do { disp = db_get_value((loc), (1), (1)); (loc) += (1); } while (0); | |||
942 | addrp->disp = disp; | |||
943 | addrp->base = db_reg[size][rm]; | |||
944 | break; | |||
945 | case 2: | |||
946 | get_value_inc(disp, loc, 4, 0)do { disp = db_get_value((loc), (4), (0)); (loc) += (4); } while (0); | |||
947 | addrp->disp = disp; | |||
948 | addrp->base = db_reg[size][rm]; | |||
949 | break; | |||
950 | } | |||
951 | return (loc); | |||
952 | } | |||
953 | ||||
954 | void | |||
955 | db_print_address(char *seg, int size, struct i_addr *addrp) | |||
956 | { | |||
957 | if (addrp->is_reg) { | |||
| ||||
958 | db_printf("%s", db_reg[size][addrp->disp]); | |||
959 | return; | |||
960 | } | |||
961 | ||||
962 | if (seg) | |||
963 | db_printf("%s:", seg); | |||
964 | ||||
965 | db_printsym((vaddr_t)addrp->disp, DB_STGY_ANY0, db_printf); | |||
966 | if (addrp->base != 0 || addrp->index != 0) { | |||
967 | db_printf("("); | |||
968 | if (addrp->base) | |||
969 | db_printf("%s", addrp->base); | |||
970 | if (addrp->index) | |||
971 | db_printf(",%s,%d", addrp->index, 1<<addrp->ss); | |||
972 | db_printf(")"); | |||
973 | } | |||
974 | } | |||
975 | ||||
976 | /* | |||
977 | * Disassemble 3DNow! instruction and return updated location. | |||
978 | */ | |||
979 | vaddr_t | |||
980 | db_disasm_3dnow(vaddr_t loc, int short_addr, int size, int rex, char *seg) | |||
981 | { | |||
982 | int regmodrm, sib, displacement, opcode; | |||
983 | ||||
984 | get_value_inc(regmodrm, loc, 1, 0)do { regmodrm = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
985 | get_value_inc(sib, loc, 1, 0)do { sib = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
986 | get_value_inc(displacement, loc, 1, 0)do { displacement = db_get_value((loc), (1), (0)); (loc) += ( 1); } while (0); | |||
987 | get_value_inc(opcode, loc, 1, 0)do { opcode = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
988 | ||||
989 | /* XXX fix later... */ | |||
990 | db_printf("<3DNow! instruction>"); | |||
991 | ||||
992 | return (loc); | |||
993 | } | |||
994 | ||||
995 | /* | |||
996 | * Disassemble floating-point ("escape") instruction | |||
997 | * and return updated location. | |||
998 | */ | |||
999 | vaddr_t | |||
1000 | db_disasm_esc(vaddr_t loc, int inst, int short_addr, int size, int rex, | |||
1001 | char *seg) | |||
1002 | { | |||
1003 | int regmodrm; | |||
1004 | struct finst *fp; | |||
1005 | int mod; | |||
1006 | struct i_addr address; | |||
1007 | char * name; | |||
1008 | ||||
1009 | get_value_inc(regmodrm, loc, 1, 0)do { regmodrm = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
1010 | fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm, 0)((((regmodrm)>>3)&0x7) + (((0) & 0x4) << 1 ))]; | |||
1011 | mod = f_mod(regmodrm)((regmodrm)>>6); | |||
1012 | if (mod != 3) { | |||
1013 | if (*fp->f_name == '\0') { | |||
1014 | db_printf("<bad instruction>"); | |||
1015 | return (loc); | |||
1016 | } | |||
1017 | ||||
1018 | /* | |||
1019 | * Normal address modes. | |||
1020 | */ | |||
1021 | loc = db_read_address(loc, short_addr, regmodrm, rex, &address); | |||
1022 | db_printf("%s", fp->f_name); | |||
1023 | switch (fp->f_size) { | |||
1024 | case SNGL4: | |||
1025 | db_printf("s"); | |||
1026 | break; | |||
1027 | case DBLR5: | |||
1028 | db_printf("l"); | |||
1029 | break; | |||
1030 | case EXTR6: | |||
1031 | db_printf("t"); | |||
1032 | break; | |||
1033 | case WORD1: | |||
1034 | db_printf("s"); | |||
1035 | break; | |||
1036 | case LONG2: | |||
1037 | db_printf("l"); | |||
1038 | break; | |||
1039 | case QUAD3: | |||
1040 | db_printf("q"); | |||
1041 | break; | |||
1042 | default: | |||
1043 | break; | |||
1044 | } | |||
1045 | db_printf("\t"); | |||
1046 | db_print_address(seg, BYTE0, &address); | |||
1047 | } else { | |||
1048 | /* | |||
1049 | * 'reg-reg' - special formats | |||
1050 | */ | |||
1051 | switch (fp->f_rrmode) { | |||
1052 | case op2(ST,STI)((31)|((32)<<8)): | |||
1053 | name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | |||
1054 | db_printf("%s\t%%st,%%st(%d)",name, f_rm(regmodrm, 0)(((regmodrm)&0x7) + (((0) & 0x1) << 3))); | |||
1055 | break; | |||
1056 | case op2(STI,ST)((32)|((31)<<8)): | |||
1057 | name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | |||
1058 | db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm, 0)(((regmodrm)&0x7) + (((0) & 0x1) << 3))); | |||
1059 | break; | |||
1060 | case op1(STI)(32): | |||
1061 | name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; | |||
1062 | db_printf("%s\t%%st(%d)",name, f_rm(regmodrm, 0)(((regmodrm)&0x7) + (((0) & 0x1) << 3))); | |||
1063 | break; | |||
1064 | case op1(X)(33): | |||
1065 | name = ((char * const *)fp->f_rrname)[f_rm(regmodrm,0)(((regmodrm)&0x7) + (((0) & 0x1) << 3))]; | |||
1066 | if (*name == '\0') | |||
1067 | goto bad; | |||
1068 | db_printf("%s", name); | |||
1069 | break; | |||
1070 | case op1(XA)(34): | |||
1071 | name = ((char * const *)fp->f_rrname)[f_rm(regmodrm,0)(((regmodrm)&0x7) + (((0) & 0x1) << 3))]; | |||
1072 | if (*name == '\0') | |||
1073 | goto bad; | |||
1074 | db_printf("%s\t%%ax", name); | |||
1075 | break; | |||
1076 | default: | |||
1077 | bad: | |||
1078 | db_printf("<bad instruction>"); | |||
1079 | break; | |||
1080 | } | |||
1081 | } | |||
1082 | ||||
1083 | return (loc); | |||
1084 | } | |||
1085 | ||||
1086 | /* | |||
1087 | * Disassemble instruction at 'loc'. 'altfmt' specifies an | |||
1088 | * (optional) alternate format. Return address of start of | |||
1089 | * next instruction. | |||
1090 | */ | |||
1091 | vaddr_t | |||
1092 | db_disasm(vaddr_t loc, int altfmt) | |||
1093 | { | |||
1094 | int inst; | |||
1095 | int size; | |||
1096 | int short_addr; | |||
1097 | char * seg; | |||
1098 | struct inst * ip; | |||
1099 | char * i_name; | |||
1100 | int i_size; | |||
1101 | int i_mode; | |||
1102 | int regmodrm = 0; | |||
1103 | int first; | |||
1104 | int displ; | |||
1105 | int prefix; | |||
1106 | long imm; | |||
1107 | int imm2; | |||
1108 | int len; | |||
1109 | int rex = 0; | |||
1110 | int segovr_grp; | |||
1111 | int repe, repne; | |||
1112 | struct i_addr address; | |||
1113 | vaddr_t loc_orig = loc; | |||
1114 | char tmpfmt[28]; | |||
1115 | ||||
1116 | get_value_inc(inst, loc, 1, 0)do { inst = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
| ||||
1117 | short_addr = 0; | |||
1118 | size = LONG2; | |||
1119 | seg = 0; | |||
1120 | segovr_grp = 0; | |||
1121 | repe = 0; | |||
1122 | repne = 0; | |||
1123 | ||||
1124 | /* | |||
1125 | * Get prefixes | |||
1126 | */ | |||
1127 | prefix = 1; | |||
1128 | do { | |||
1129 | switch (inst) { | |||
1130 | case 0x66: /* data16 */ | |||
1131 | size = WORD1; | |||
1132 | break; | |||
1133 | case 0x67: | |||
1134 | short_addr = 1; | |||
1135 | break; | |||
1136 | case 0x26: | |||
1137 | segovr_grp++; | |||
1138 | db_printf(" <segment override prefix ignored>"); | |||
1139 | break; | |||
1140 | case 0x36: | |||
1141 | db_printf(" <segment override prefix ignored>"); | |||
1142 | segovr_grp++; | |||
1143 | break; | |||
1144 | case 0x2e: | |||
1145 | db_printf(" <segment override prefix ignored>"); | |||
1146 | segovr_grp++; | |||
1147 | break; | |||
1148 | case 0x3e: | |||
1149 | db_printf(" <segment override prefix ignored>"); | |||
1150 | segovr_grp++; | |||
1151 | break; | |||
1152 | case 0x64: | |||
1153 | segovr_grp++; | |||
1154 | seg = "%fs"; | |||
1155 | break; | |||
1156 | case 0x65: | |||
1157 | segovr_grp++; | |||
1158 | seg = "%gs"; | |||
1159 | break; | |||
1160 | case 0xf0: | |||
1161 | db_printf("lock "); | |||
1162 | break; | |||
1163 | case 0xf2: | |||
1164 | repne++; | |||
1165 | break; | |||
1166 | case 0xf3: | |||
1167 | repe++; | |||
1168 | break; | |||
1169 | default: | |||
1170 | prefix = 0; | |||
1171 | break; | |||
1172 | } | |||
1173 | if (prefix
| |||
1174 | get_value_inc(inst, loc, 1, 0)do { inst = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
1175 | } while (prefix); | |||
1176 | if (segovr_grp
| |||
1177 | seg = "<bad segment override prefix combination> "; | |||
1178 | if (repe
| |||
1179 | db_printf("<bad repeat prefex combination> "); | |||
1180 | else if (repe
| |||
1181 | db_printf("repe "); /* XXX "rep" if not CMPSx or SCASx */ | |||
1182 | else if (repne
| |||
1183 | db_printf("repne "); | |||
1184 | ||||
1185 | if (inst >= 0x40 && inst <= 0x4f) { | |||
1186 | // rex page 14 | |||
1187 | rex = inst; | |||
1188 | if (REX_W(rex)(((rex) & 0x8) == 0x8)) | |||
1189 | size = QUAD3; | |||
1190 | get_value_inc(inst, loc, 1, 0)do { inst = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
1191 | } | |||
1192 | ||||
1193 | if (inst
| |||
1194 | loc = db_disasm_esc(loc, inst, short_addr, size, rex, seg); | |||
1195 | goto done; | |||
1196 | } | |||
1197 | ||||
1198 | if (inst == 0x0f) { | |||
1199 | get_value_inc(inst, loc, 1, 0)do { inst = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
1200 | if (inst == 0x0f) { | |||
1201 | loc = db_disasm_3dnow(loc, short_addr, size, rex, seg); | |||
1202 | goto done; | |||
1203 | } | |||
1204 | ip = db_inst_0f[inst>>4]; | |||
1205 | if (ip == 0) | |||
1206 | ip = &db_bad_inst; | |||
1207 | else | |||
1208 | ip = &ip[inst&0xf]; | |||
1209 | } else { | |||
1210 | ip = &db_inst_table[inst]; | |||
1211 | } | |||
1212 | ||||
1213 | if (ip->i_has_modrm) { | |||
1214 | get_value_inc(regmodrm, loc, 1, 0)do { regmodrm = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
1215 | loc = db_read_address(loc, short_addr, regmodrm, rex, &address); | |||
1216 | } | |||
1217 | ||||
1218 | i_name = ip->i_name; | |||
1219 | i_size = ip->i_size; | |||
1220 | i_mode = ip->i_mode; | |||
1221 | ||||
1222 | if (i_size == RDEP9) { | |||
1223 | /* sub-table to handle dependency on reg from ModR/M byte */ | |||
1224 | ip = (struct inst *)ip->i_extra; | |||
1225 | ip = &ip[f_reg(regmodrm, 0)((((regmodrm)>>3)&0x7) + (((0) & 0x4) << 1 ))]; | |||
1226 | i_name = ip->i_name; | |||
1227 | i_mode = ip->i_mode; | |||
1228 | i_size = ip->i_size; | |||
1229 | } else if (i_name == NULL((void *)0)) { | |||
1230 | i_name = ((char **)ip->i_extra)[f_reg(regmodrm, 0)((((regmodrm)>>3)&0x7) + (((0) & 0x4) << 1 ))]; | |||
1231 | } else if (ip->i_extra == db_Grp3) { | |||
1232 | ip = (struct inst *)ip->i_extra; | |||
1233 | ip = &ip[f_reg(regmodrm, 0)((((regmodrm)>>3)&0x7) + (((0) & 0x4) << 1 ))]; | |||
1234 | i_name = ip->i_name; | |||
1235 | i_mode = ip->i_mode; | |||
1236 | } | |||
1237 | ||||
1238 | /* ModR/M-specific operation? */ | |||
1239 | if ((i_mode & 0xFF) == MEx38) { | |||
1240 | if (f_mod(regmodrm)((regmodrm)>>6) != 3) | |||
1241 | i_mode = op1(E)(1); | |||
1242 | else { | |||
1243 | /* unknown extension? */ | |||
1244 | if (f_rm(regmodrm, 0)(((regmodrm)&0x7) + (((0) & 0x1) << 3)) > (i_mode >> 8)) | |||
1245 | i_name = ""; | |||
1246 | else { | |||
1247 | /* skip to the specific op */ | |||
1248 | int i = f_rm(regmodrm, 0)(((regmodrm)&0x7) + (((0) & 0x1) << 3)); | |||
1249 | i_name = ip->i_extra; | |||
1250 | while (i-- > 0) | |||
1251 | while (*i_name++) | |||
1252 | ; | |||
1253 | } | |||
1254 | i_mode = 0; | |||
1255 | } | |||
1256 | } | |||
1257 | ||||
1258 | if (i_size == SDEP7) { | |||
1259 | if (size == WORD1) | |||
1260 | db_printf("%s", i_name); | |||
1261 | else if (size == LONG2) | |||
1262 | db_printf("%s", (char *)ip->i_extra); | |||
1263 | else { | |||
1264 | char *cp = ip->i_extra; | |||
1265 | while (*cp) | |||
1266 | cp++; | |||
1267 | cp++; | |||
1268 | db_printf("%s", cp); | |||
1269 | } | |||
1270 | } else { | |||
1271 | db_printf("%s", i_name); | |||
1272 | if (i_size != NONE8) { | |||
1273 | if (i_size == BYTE0) { | |||
1274 | db_printf("b"); | |||
1275 | size = BYTE0; | |||
1276 | } else if (REX_W(rex)(((rex) & 0x8) == 0x8)) { | |||
1277 | db_printf("q"); | |||
1278 | size = QUAD3; | |||
1279 | } else if (i_size == WORD1) { | |||
1280 | db_printf("w"); | |||
1281 | size = WORD1; | |||
1282 | } else if (i_size == QUAD3) { | |||
1283 | size = QUAD3; | |||
1284 | db_printf("q"); | |||
1285 | } else if (size == WORD1) { | |||
1286 | db_printf("w"); | |||
1287 | } else { | |||
1288 | db_printf("l"); | |||
1289 | } | |||
1290 | } | |||
1291 | } | |||
1292 | db_printf("\t"); | |||
1293 | for (first = 1; i_mode != 0; i_mode >>= 8, first = 0) { | |||
1294 | if (!first
| |||
1295 | db_printf(","); | |||
1296 | ||||
1297 | switch (i_mode & 0xFF) { | |||
1298 | case E1: //XXX | |||
1299 | db_print_address(seg, size, &address); | |||
1300 | break; | |||
1301 | case Eind2: //XXX | |||
1302 | db_printf("*"); | |||
1303 | db_print_address(seg, size, &address); | |||
1304 | break; | |||
1305 | case Ew3: //XXX | |||
1306 | db_print_address(seg, WORD1, &address); | |||
1307 | break; | |||
1308 | case Eb4: //XXX | |||
1309 | db_print_address(seg, BYTE0, &address); | |||
1310 | break; | |||
1311 | case R5: | |||
1312 | db_printf("%s", db_reg[size][f_reg(regmodrm, rex)((((regmodrm)>>3)&0x7) + (((rex) & 0x4) << 1))]); | |||
1313 | break; | |||
1314 | case Rw6: | |||
1315 | db_printf("%s", db_reg[WORD1][f_reg(regmodrm, rex)((((regmodrm)>>3)&0x7) + (((rex) & 0x4) << 1))]); | |||
1316 | break; | |||
1317 | case Ri7: | |||
1318 | db_printf("%s", db_reg[size][f_rm(inst, rex)(((inst)&0x7) + (((rex) & 0x1) << 3))]); | |||
1319 | break; | |||
1320 | case Ril36: | |||
1321 | db_printf("%s", db_reg[LONG2][f_rm(inst, rex)(((inst)&0x7) + (((rex) & 0x1) << 3))]); | |||
1322 | break; | |||
1323 | case S8: | |||
1324 | db_printf("%s", db_seg_reg[f_reg(regmodrm, 0)((((regmodrm)>>3)&0x7) + (((0) & 0x4) << 1 ))]); | |||
1325 | break; | |||
1326 | case Si9: | |||
1327 | db_printf("%s", db_seg_reg[f_reg(inst, 0)((((inst)>>3)&0x7) + (((0) & 0x4) << 1))]); | |||
1328 | break; | |||
1329 | case A10: | |||
1330 | db_printf("%s", db_reg[size][0]); /* acc */ | |||
1331 | break; | |||
1332 | case BX11: | |||
1333 | if (seg) | |||
1334 | db_printf("%s:", seg); | |||
1335 | db_printf("(%s)", short_addr ? "%ebx" : "%rbx"); | |||
1336 | break; | |||
1337 | case CL12: | |||
1338 | db_printf("%%cl"); | |||
1339 | break; | |||
1340 | case DX13: | |||
1341 | db_printf("%%dx"); | |||
1342 | break; | |||
1343 | case SI14: | |||
1344 | if (seg) | |||
1345 | db_printf("%s:", seg); | |||
1346 | db_printf("(%s)", short_addr ? "%esi" : "%rsi"); | |||
1347 | break; | |||
1348 | case DI15: | |||
1349 | db_printf("%%es:(%s)", short_addr ? "%edi" : "%rdi"); | |||
1350 | break; | |||
1351 | case CR16: | |||
1352 | db_printf("%%cr%d", f_reg(regmodrm, rex)((((regmodrm)>>3)&0x7) + (((rex) & 0x4) << 1))); | |||
1353 | break; | |||
1354 | case DR17: | |||
1355 | db_printf("%%dr%d", f_reg(regmodrm, rex)((((regmodrm)>>3)&0x7) + (((rex) & 0x4) << 1))); | |||
1356 | break; | |||
1357 | case TR18: //XXX | |||
1358 | db_printf("%%tr%d", f_reg(regmodrm, rex)((((regmodrm)>>3)&0x7) + (((rex) & 0x4) << 1))); | |||
1359 | break; | |||
1360 | case I19: | |||
1361 | len = db_lengths[size]; | |||
1362 | get_value_inc(imm, loc, len, 0)do { imm = db_get_value((loc), (len), (0)); (loc) += (len); } while (0); | |||
1363 | db_printf("$%s", db_format(tmpfmt, sizeof tmpfmt, | |||
1364 | (int)imm, DB_FORMAT_N3, 1, 0)); | |||
1365 | break; | |||
1366 | case Is20: | |||
1367 | len = db_lengths[size]; | |||
1368 | get_value_inc(imm, loc, len, 1)do { imm = db_get_value((loc), (len), (1)); (loc) += (len); } while (0); | |||
1369 | db_printf("$%s", db_format(tmpfmt, sizeof tmpfmt, | |||
1370 | (int)imm, DB_FORMAT_R2, 1, 0)); | |||
1371 | break; | |||
1372 | case Ib21: | |||
1373 | get_value_inc(imm, loc, 1, 0)do { imm = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
1374 | db_printf("$%s", db_format(tmpfmt, sizeof tmpfmt, | |||
1375 | (int)imm, DB_FORMAT_N3, 1, 0)); | |||
1376 | break; | |||
1377 | case Iba37: | |||
1378 | get_value_inc(imm, loc, 1, 0)do { imm = db_get_value((loc), (1), (0)); (loc) += (1); } while (0); | |||
1379 | if (imm != 0x0a) | |||
1380 | db_printf("$%s", db_format(tmpfmt, sizeof tmpfmt, | |||
1381 | (int)imm, DB_FORMAT_N3, 1, 0)); | |||
1382 | break; | |||
1383 | case Ibs22: //XXX | |||
1384 | get_value_inc(imm, loc, 1, 1)do { imm = db_get_value((loc), (1), (1)); (loc) += (1); } while (0); | |||
1385 | if (size == WORD1) | |||
1386 | imm &= 0xFFFF; | |||
1387 | db_printf("$%s", db_format(tmpfmt, sizeof tmpfmt, | |||
1388 | (int)imm, DB_FORMAT_R2, 1, 0)); | |||
1389 | break; | |||
1390 | case Iw23: | |||
1391 | get_value_inc(imm, loc, 2, 0)do { imm = db_get_value((loc), (2), (0)); (loc) += (2); } while (0); | |||
1392 | db_printf("$%s", db_format(tmpfmt, sizeof tmpfmt, | |||
1393 | (int)imm, DB_FORMAT_N3, 1, 0)); | |||
1394 | break; | |||
1395 | case Iq24: | |||
1396 | get_value_inc(imm, loc, 8, 1)do { imm = db_get_value((loc), (8), (1)); (loc) += (8); } while (0); | |||
1397 | db_printf("$%s", db_format(tmpfmt, sizeof tmpfmt, | |||
1398 | (int)((imm >> 32) & 0xffffffff), DB_FORMAT_R2, 1, 0)); | |||
1399 | db_printf(" %s", db_format(tmpfmt, sizeof tmpfmt, | |||
1400 | (int)(imm & 0xffffffff), DB_FORMAT_R2, 1, 0)); | |||
1401 | break; | |||
1402 | case O25: //XXX | |||
1403 | if (short_addr) | |||
1404 | get_value_inc(displ, loc, 2, 1)do { displ = db_get_value((loc), (2), (1)); (loc) += (2); } while (0); | |||
1405 | else | |||
1406 | get_value_inc(displ, loc, 4, 1)do { displ = db_get_value((loc), (4), (1)); (loc) += (4); } while (0); | |||
1407 | if (seg) | |||
1408 | db_printf("%s:%s", seg, db_format(tmpfmt, | |||
1409 | sizeof tmpfmt, displ, DB_FORMAT_R2, 1, 0)); | |||
1410 | else | |||
1411 | db_printsym((vaddr_t)displ, DB_STGY_ANY0, | |||
1412 | db_printf); | |||
1413 | break; | |||
1414 | case Db26: //XXX | |||
1415 | get_value_inc(displ, loc, 1, 1)do { displ = db_get_value((loc), (1), (1)); (loc) += (1); } while (0); | |||
1416 | displ += loc; | |||
1417 | if (size == WORD1) | |||
1418 | displ &= 0xFFFF; | |||
1419 | db_printsym((vaddr_t)displ, DB_STGY_XTRN1, db_printf); | |||
1420 | break; | |||
1421 | case Dl27: //XXX | |||
1422 | len = db_lengths[size]; | |||
1423 | get_value_inc(displ, loc, len, 0)do { displ = db_get_value((loc), (len), (0)); (loc) += (len); } while (0); | |||
1424 | displ += loc; | |||
1425 | if (size == WORD1) | |||
1426 | displ &= 0xFFFF; | |||
1427 | db_printsym((vaddr_t)displ, DB_STGY_XTRN1, db_printf); | |||
1428 | break; | |||
1429 | case o128: //XXX | |||
1430 | db_printf("$1"); | |||
1431 | break; | |||
1432 | case o329: //XXX | |||
1433 | db_printf("$3"); | |||
1434 | break; | |||
1435 | case OS30: //XXX | |||
1436 | len = db_lengths[size]; | |||
1437 | get_value_inc(imm, loc, len, 0)do { imm = db_get_value((loc), (len), (0)); (loc) += (len); } while (0); /* offset */ | |||
1438 | get_value_inc(imm2, loc, 2, 0)do { imm2 = db_get_value((loc), (2), (0)); (loc) += (2); } while (0); /* segment */ | |||
1439 | db_printf("$0x%#x", imm2); | |||
1440 | break; | |||
1441 | } | |||
1442 | } | |||
1443 | ||||
1444 | if (altfmt == 0 && (inst == 0xe9 || inst == 0xeb)) { | |||
1445 | /* | |||
1446 | * GAS pads to longword boundary after unconditional jumps. | |||
1447 | */ | |||
1448 | loc = (loc + (4-1)) & ~(4-1); | |||
1449 | } | |||
1450 | done: | |||
1451 | if (loc - loc_orig > 15) | |||
1452 | db_printf(" <instruction too long>"); | |||
1453 | if (altfmt) { | |||
1454 | db_printf("\n\t"); | |||
1455 | while (loc_orig < loc) { | |||
1456 | get_value_inc(imm, loc_orig, 1, 0)do { imm = db_get_value((loc_orig), (1), (0)); (loc_orig) += ( 1); } while (0); | |||
1457 | if (imm < 0x10) | |||
1458 | db_printf("0"); | |||
1459 | db_printf("%x ", (int)imm); | |||
1460 | } | |||
1461 | } | |||
1462 | db_printf("\n"); | |||
1463 | return (loc); | |||
1464 | } |