1 | /*
|
---|
2 | * mdbdis86.c for mdb.c - 8086-386 and 8087 disassembler
|
---|
3 | * From Bruce Evans db
|
---|
4 | */
|
---|
5 |
|
---|
6 | #include "mdb.h"
|
---|
7 | #include <stddef.h>
|
---|
8 | #include <stdio.h>
|
---|
9 | #include <sys/types.h>
|
---|
10 | #include "proto.h"
|
---|
11 |
|
---|
12 | struct address_s
|
---|
13 | {
|
---|
14 | off_t off;
|
---|
15 | off_t base;
|
---|
16 | };
|
---|
17 |
|
---|
18 | PRIVATE int bits32;
|
---|
19 | PRIVATE struct address_s uptr;
|
---|
20 |
|
---|
21 | FORWARD _PROTOTYPE( u8_t get8, (void) );
|
---|
22 | FORWARD _PROTOTYPE( u16_t get16, (void) );
|
---|
23 | FORWARD _PROTOTYPE( u32_t get32, (void) );
|
---|
24 | FORWARD _PROTOTYPE( u8_t peek_byte, (off_t addr) );
|
---|
25 | FORWARD _PROTOTYPE( u16_t peek_word, (off_t addr) );
|
---|
26 | FORWARD _PROTOTYPE( int puti, (void) );
|
---|
27 | FORWARD _PROTOTYPE( int outsegaddr, (struct address_s *addr) );
|
---|
28 | FORWARD _PROTOTYPE( int outssegaddr, (struct address_s *addr) );
|
---|
29 | FORWARD _PROTOTYPE( int show1instruction , (void));
|
---|
30 |
|
---|
31 | /************************* UNASM ******************************/
|
---|
32 |
|
---|
33 |
|
---|
34 | #define LINDIRECT '['
|
---|
35 | #define RINDIRECT ']'
|
---|
36 |
|
---|
37 | #define BASE_MASK 0x07
|
---|
38 | #define INDEX_MASK 0x38
|
---|
39 | #define INDEX_SHIFT 3
|
---|
40 | #define MOD_MASK 0xC0 /* mod reg r/m is mmrrrRRR */
|
---|
41 | #define REG_MOD 0xC0
|
---|
42 | #define MEM0_MOD 0x00
|
---|
43 | #define MEM1_MOD 0x40
|
---|
44 | #define MEM2_MOD 0x80
|
---|
45 | #define REG_MASK 0x38
|
---|
46 | #define REG_SHIFT 3
|
---|
47 | #define RM_MASK 0x07
|
---|
48 | #define RM_SHIFT 0
|
---|
49 | #define SS_MASK 0xC0
|
---|
50 | #define SS_SHIFT 6
|
---|
51 |
|
---|
52 | #define SIGNBIT 0x02 /* opcode bits xxxxxxsw for immediates */
|
---|
53 | #define WORDBIT 0x01
|
---|
54 | #define TOREGBIT 0x02 /* opcode bit for non-immediates */
|
---|
55 |
|
---|
56 | #define MAX_SIGNED_CHAR 0x7F /* will assume 2's complement */
|
---|
57 | #define MAX_UNSIGNED_CHAR 0xFF
|
---|
58 |
|
---|
59 | typedef unsigned opcode_pt; /* promote to unsigned and not int */
|
---|
60 |
|
---|
61 | typedef int reg_pt;
|
---|
62 | typedef int su16_t;
|
---|
63 | typedef int su8_pt;
|
---|
64 |
|
---|
65 | FORWARD _PROTOTYPE( su8_pt get8s , (void));
|
---|
66 | FORWARD _PROTOTYPE( void getmodregrm , (void));
|
---|
67 | FORWARD _PROTOTYPE( void i_00_to_3f , (opcode_pt opc ));
|
---|
68 | FORWARD _PROTOTYPE( void i_40_to_5f , (opcode_pt opc ));
|
---|
69 | FORWARD _PROTOTYPE( void i_60_to_6f , (opcode_pt opc ));
|
---|
70 | FORWARD _PROTOTYPE( void i_70_to_7f , (opcode_pt opc ));
|
---|
71 | FORWARD _PROTOTYPE( void i_80 , (opcode_pt opc ));
|
---|
72 | FORWARD _PROTOTYPE( void i_88 , (opcode_pt opc ));
|
---|
73 | FORWARD _PROTOTYPE( void i_90 , (opcode_pt opc ));
|
---|
74 | FORWARD _PROTOTYPE( void i_98 , (opcode_pt opc ));
|
---|
75 | FORWARD _PROTOTYPE( void i_a0 , (opcode_pt opc ));
|
---|
76 | FORWARD _PROTOTYPE( void i_a8 , (opcode_pt opc ));
|
---|
77 | FORWARD _PROTOTYPE( void i_b0 , (opcode_pt opc ));
|
---|
78 | FORWARD _PROTOTYPE( void i_b8 , (opcode_pt opc ));
|
---|
79 | FORWARD _PROTOTYPE( void i_c0 , (opcode_pt opc ));
|
---|
80 | FORWARD _PROTOTYPE( void i_c8 , (opcode_pt opc ));
|
---|
81 | FORWARD _PROTOTYPE( void i_d0 , (opcode_pt opc ));
|
---|
82 | FORWARD _PROTOTYPE( void i_d8 , (opcode_pt opc ));
|
---|
83 | FORWARD _PROTOTYPE( void i_e0 , (opcode_pt opc ));
|
---|
84 | FORWARD _PROTOTYPE( void i_e8 , (opcode_pt opc ));
|
---|
85 | FORWARD _PROTOTYPE( void i_f0 , (opcode_pt opc ));
|
---|
86 | FORWARD _PROTOTYPE( void i_f8 , (opcode_pt opc ));
|
---|
87 | FORWARD _PROTOTYPE( void outad , (opcode_pt opc ));
|
---|
88 | FORWARD _PROTOTYPE( void outad1 , (opcode_pt opc ));
|
---|
89 | FORWARD _PROTOTYPE( void outalorx , (opcode_pt opc ));
|
---|
90 | FORWARD _PROTOTYPE( void outax , (void));
|
---|
91 | FORWARD _PROTOTYPE( void outbptr , (void));
|
---|
92 | FORWARD _PROTOTYPE( void outbwptr , (opcode_pt opc ));
|
---|
93 | FORWARD _PROTOTYPE( void outea , (opcode_pt wordflags ));
|
---|
94 | FORWARD _PROTOTYPE( void outf1 , (void));
|
---|
95 | FORWARD _PROTOTYPE( void out32offset , (void));
|
---|
96 | FORWARD _PROTOTYPE( void outfishy , (void));
|
---|
97 | FORWARD _PROTOTYPE( void outgetaddr , (void));
|
---|
98 | FORWARD _PROTOTYPE( void outimmed , (opcode_pt signwordflag ));
|
---|
99 | FORWARD _PROTOTYPE( void outpc , (off_t pc ));
|
---|
100 | FORWARD _PROTOTYPE( void outsegpc , (void));
|
---|
101 | FORWARD _PROTOTYPE( void oututstr , (char *s ));
|
---|
102 | FORWARD _PROTOTYPE( void outword , (void));
|
---|
103 | FORWARD _PROTOTYPE( void outwptr , (void));
|
---|
104 | FORWARD _PROTOTYPE( void outwsize , (void));
|
---|
105 | FORWARD _PROTOTYPE( void pagef , (void));
|
---|
106 | FORWARD _PROTOTYPE( void shift , (opcode_pt opc ));
|
---|
107 | FORWARD _PROTOTYPE( void checkmemory , (void));
|
---|
108 | FORWARD _PROTOTYPE( void CL , (void));
|
---|
109 | FORWARD _PROTOTYPE( void Eb , (void));
|
---|
110 | FORWARD _PROTOTYPE( void Ev , (void));
|
---|
111 | FORWARD _PROTOTYPE( void EvGv , (void));
|
---|
112 | FORWARD _PROTOTYPE( void EvIb , (void));
|
---|
113 | FORWARD _PROTOTYPE( void Ew , (void));
|
---|
114 | FORWARD _PROTOTYPE( void EwRw , (void));
|
---|
115 | FORWARD _PROTOTYPE( void Gv , (void));
|
---|
116 | FORWARD _PROTOTYPE( void Gv1 , (void));
|
---|
117 | FORWARD _PROTOTYPE( void GvEv , (void));
|
---|
118 | FORWARD _PROTOTYPE( void GvEw , (void));
|
---|
119 | FORWARD _PROTOTYPE( void GvM , (void));
|
---|
120 | FORWARD _PROTOTYPE( void GvMa , (void));
|
---|
121 | FORWARD _PROTOTYPE( void GvMp , (void));
|
---|
122 | FORWARD _PROTOTYPE( void Ib , (void));
|
---|
123 | FORWARD _PROTOTYPE( void Iw , (void));
|
---|
124 | FORWARD _PROTOTYPE( void Iv , (void));
|
---|
125 | FORWARD _PROTOTYPE( void Jb , (void));
|
---|
126 | FORWARD _PROTOTYPE( void Jv , (void));
|
---|
127 | FORWARD _PROTOTYPE( void Ms , (void));
|
---|
128 |
|
---|
129 | _PROTOTYPE( typedef void (*pfv_t),(opcode_pt opc ));
|
---|
130 |
|
---|
131 | PRIVATE pfv_t optable[] =
|
---|
132 | {
|
---|
133 | i_00_to_3f,
|
---|
134 | i_00_to_3f,
|
---|
135 | i_00_to_3f,
|
---|
136 | i_00_to_3f,
|
---|
137 | i_00_to_3f,
|
---|
138 | i_00_to_3f,
|
---|
139 | i_00_to_3f,
|
---|
140 | i_00_to_3f,
|
---|
141 | i_40_to_5f,
|
---|
142 | i_40_to_5f,
|
---|
143 | i_40_to_5f,
|
---|
144 | i_40_to_5f,
|
---|
145 | i_60_to_6f,
|
---|
146 | i_60_to_6f,
|
---|
147 | i_70_to_7f,
|
---|
148 | i_70_to_7f,
|
---|
149 | i_80,
|
---|
150 | i_88,
|
---|
151 | i_90,
|
---|
152 | i_98,
|
---|
153 | i_a0,
|
---|
154 | i_a8,
|
---|
155 | i_b0,
|
---|
156 | i_b8,
|
---|
157 | i_c0,
|
---|
158 | i_c8,
|
---|
159 | i_d0,
|
---|
160 | i_d8,
|
---|
161 | i_e0,
|
---|
162 | i_e8,
|
---|
163 | i_f0,
|
---|
164 | i_f8,
|
---|
165 | };
|
---|
166 |
|
---|
167 | PRIVATE char fishy[] = "???";
|
---|
168 | PRIVATE char movtab[] = "mov\t";
|
---|
169 |
|
---|
170 | PRIVATE char *genreg[] =
|
---|
171 | {
|
---|
172 | "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
|
---|
173 | "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
|
---|
174 | "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
|
---|
175 | };
|
---|
176 |
|
---|
177 | PRIVATE char *segreg[] =
|
---|
178 | {
|
---|
179 | "es", "cs", "ss", "ds", "fs", "gs", "?s", "?s",
|
---|
180 | };
|
---|
181 |
|
---|
182 | PRIVATE char *indreg[] =
|
---|
183 | {
|
---|
184 | "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx",
|
---|
185 | };
|
---|
186 |
|
---|
187 | PRIVATE char *str_00_to_3f[] =
|
---|
188 | {
|
---|
189 | /* index by (opcode >> 3) & 7 */
|
---|
190 | "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp",
|
---|
191 | };
|
---|
192 |
|
---|
193 | PRIVATE char *sstr_00_to_3f[] =
|
---|
194 | {
|
---|
195 | /* index ((opc>>2) & 0x0E) + (opc & 7) - 6 */
|
---|
196 | "push\tes", "pop\tes", "push\tcs", "pop\tcs",
|
---|
197 | "push\tss", "pop\tss", "push\tds", "pop\tds",
|
---|
198 | "es:", "daa", "cs:", "das", "ss:", "aaa", "ds:", "aas",
|
---|
199 | };
|
---|
200 |
|
---|
201 | PRIVATE char *sstr_0f[] =
|
---|
202 | {
|
---|
203 | "push\tfs", "pop\tfs", fishy, "bt\t", "shld\t", "shld\t", fishy, fishy,
|
---|
204 | "push\tgs", "pop\tgs", fishy, "bts\t", "shrd\t", "shrd\t", fishy, "imul\t",
|
---|
205 | fishy, fishy, "lss\t", "btr\t", "lfs\t", "lgs\t", "movzx\t", "movzx\t",
|
---|
206 | fishy, fishy, "", "btc\t", "bsf\t", "bsr\t", "movsx\t", "movsx\t",
|
---|
207 | };
|
---|
208 |
|
---|
209 | PRIVATE char *ssstr_0f[] =
|
---|
210 | {
|
---|
211 | "sldt\t", "str\t", "lldt\t", "ltr\t", "verr\t", "verw\t", fishy, fishy,
|
---|
212 | "sgdt\t", "sidt\t", "lgdt\t", "lidt\t", "smsw\t", fishy, "lmsw\t", fishy,
|
---|
213 | fishy, fishy, fishy, fishy, "bt\t", "bts\t", "btr\t", "btc\t",
|
---|
214 | };
|
---|
215 |
|
---|
216 | PRIVATE char *str_40_to_5f[] =
|
---|
217 | {
|
---|
218 | /* index by (opcode >> 3) & 3 */
|
---|
219 | "inc\t", "dec\t", "push\t", "pop\t",
|
---|
220 | };
|
---|
221 |
|
---|
222 | PRIVATE char *str_60_to_6f[] =
|
---|
223 | {
|
---|
224 | "pusha", "popa", "bound\t", "arpl\t", "fs:", "gs:", "os:", "as:",
|
---|
225 | "push\t", "imul\t", "push\t", "imul\t", "insb", "ins", "outsb", "outs",
|
---|
226 | };
|
---|
227 |
|
---|
228 | PRIVATE char *str_flags[] =
|
---|
229 | {
|
---|
230 | /* opcodes 0x70 to 0x7F, and 0x0F80 to 0x0F9F */
|
---|
231 | "o", "no", "b", "nb", "z", "nz", "be", "a",
|
---|
232 | "s", "ns", "pe", "po", "l", "ge", "le", "g",
|
---|
233 | };
|
---|
234 |
|
---|
235 | PRIVATE char *str_98[] =
|
---|
236 | {
|
---|
237 | "cbw", "cwd", "call\t", "wait", "pushf", "popf", "sahf", "lahf",
|
---|
238 | "cwde", "cdq", "call\t", "wait", "pushfd", "popfd", "sahf", "lahf",
|
---|
239 | };
|
---|
240 |
|
---|
241 | PRIVATE char *str_a0[] =
|
---|
242 | {
|
---|
243 | movtab, movtab, movtab, movtab, "movsb", "movs", "cmpsb", "cmps",
|
---|
244 | };
|
---|
245 |
|
---|
246 | PRIVATE char *str_a8[] =
|
---|
247 | {
|
---|
248 | "test\t", "test\t", "stosb", "stos", "lodsb", "lods", "scasb", "scas",
|
---|
249 | };
|
---|
250 |
|
---|
251 | PRIVATE char *str_c0[] =
|
---|
252 | {
|
---|
253 | "", "", "ret\t", "ret", "les\t", "lds\t", movtab, movtab,
|
---|
254 | };
|
---|
255 |
|
---|
256 | PRIVATE char *str_c8[] =
|
---|
257 | {
|
---|
258 | "enter\t", "leave", "retf\t", "retf", "int\t3", "int\t", "into", "iret",
|
---|
259 | };
|
---|
260 |
|
---|
261 | PRIVATE char *str_d0[] =
|
---|
262 | {
|
---|
263 | "aam", "aad", "db\td6", "xlat",
|
---|
264 | };
|
---|
265 |
|
---|
266 | PRIVATE char *sstr_d0[] =
|
---|
267 | {
|
---|
268 | "rol", "ror", "rcl", "rcr", "shl", "shr", fishy, "sar",
|
---|
269 | };
|
---|
270 |
|
---|
271 | PRIVATE char *str_d8[] =
|
---|
272 | {
|
---|
273 | "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
|
---|
274 | "fld", NULL, "fst", "fstp", "fldenv", "fldcw", "fstenv", "fstcw",
|
---|
275 | "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr",
|
---|
276 | "fild", NULL, "fist", "fistp", NULL, "fld", NULL, "fstp",
|
---|
277 | "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
|
---|
278 | "fld", NULL, "fst", "fstp", "frstor", NULL, "fsave", "fstsw",
|
---|
279 | "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr",
|
---|
280 | "fild", NULL, "fist", "fistp", "fbld", "fild", "fbstp", "fistp",
|
---|
281 | };
|
---|
282 |
|
---|
283 | PRIVATE char *str1_d8[] =
|
---|
284 | {
|
---|
285 | "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
|
---|
286 | "fld", "fxch", "\0\0", NULL, "\0\10", "\0\20", "\0\30", "\0\40",
|
---|
287 | NULL, NULL, NULL, NULL, NULL, "\0\50", NULL, NULL,
|
---|
288 | NULL, NULL, NULL, NULL, "\0\60", NULL, NULL, NULL,
|
---|
289 | "fadd", "fmul", NULL, NULL, "fsubr", "fsub", "fdivr", "fdiv",
|
---|
290 | "ffree", NULL, "fst", "fstp", "fucom", "fucomp", NULL, NULL,
|
---|
291 | "faddp", "fmulp", NULL, "\0\70", "fsubrp", "fsubp", "fdivrp", "fdivp",
|
---|
292 | NULL, NULL, NULL, NULL, "\0\100", NULL, NULL, NULL,
|
---|
293 | };
|
---|
294 |
|
---|
295 | PRIVATE unsigned char size_d8[] =
|
---|
296 | {
|
---|
297 | 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 14-28, 2, 14-28, 2,
|
---|
298 | 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 0, 10, 0, 10,
|
---|
299 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 8, 8, 94-108, 0, 94-108, 2,
|
---|
300 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 10, 8, 10, 8,
|
---|
301 | };
|
---|
302 |
|
---|
303 | PRIVATE char *sstr_d8[] =
|
---|
304 | {
|
---|
305 | "fnop", NULL, NULL, NULL, /* D9D0 */
|
---|
306 | NULL, NULL, NULL, NULL,
|
---|
307 | "fchs", "fabs", NULL, NULL, /* D9E0 */
|
---|
308 | "ftst", "fxam", NULL, NULL,
|
---|
309 | "fld1", "fldl2t", "fldl2e", "fldpi", /* D9E8 */
|
---|
310 | "fldlg2", "fldln2", "fldz", NULL,
|
---|
311 | "f2xm1", "fyl2x", "fptan", "fpatan", /* D9F0 */
|
---|
312 | "fxtract", "fprem1", "fdecstp", "fincstp",
|
---|
313 | "fprem", "fyl2xp1", "fsqrt", "fsincos", /* D9F8 */
|
---|
314 | "frndint", "fscale", "fsin", "fcos",
|
---|
315 | NULL, "fucompp", NULL, NULL, /* DAE8 */
|
---|
316 | NULL, NULL, NULL, NULL,
|
---|
317 | "feni", "fdisi", "fclex", "finit", /* DBE0 */
|
---|
318 | "fsetpm", NULL, NULL, NULL,
|
---|
319 | NULL, "fcompp", NULL, NULL, /* DED8 */
|
---|
320 | NULL, NULL, NULL, NULL,
|
---|
321 | NULL, NULL, NULL, NULL, /* DFE0 */
|
---|
322 | "fstsw\tax", NULL, NULL, NULL,
|
---|
323 | };
|
---|
324 |
|
---|
325 | PRIVATE char *str_e0[] =
|
---|
326 | {
|
---|
327 | "loopnz\t", "loopz\t", "loop\t", "jcxz\t",
|
---|
328 | "in\t", "in\t", "out\t", "out\t",
|
---|
329 | };
|
---|
330 |
|
---|
331 | PRIVATE char *str_e8[] =
|
---|
332 | {
|
---|
333 | "call\t", "jmp\t", "jmp\t", "jmp\t",
|
---|
334 | "in\t", "in\t", "out\t", "out\t",
|
---|
335 | };
|
---|
336 |
|
---|
337 | PRIVATE char *str_f0[] =
|
---|
338 | {
|
---|
339 | "lock\t", "db\tf1", "repnz\t", "repz\t",
|
---|
340 | "hlt", "cmc",
|
---|
341 | /* other 2 from sstr_f0 */
|
---|
342 | };
|
---|
343 |
|
---|
344 | PRIVATE char *sstr_f0[] =
|
---|
345 | {
|
---|
346 | "test\t", fishy, "not\t", "neg\t",
|
---|
347 | "mul\t", "imul\t", "div\t", "idiv\t",
|
---|
348 | };
|
---|
349 |
|
---|
350 | PRIVATE char *str_f8[] =
|
---|
351 | {
|
---|
352 | "clc", "stc", "cli", "sti",
|
---|
353 | "cld", "std",
|
---|
354 | /* other 2 from sstr_f8 */
|
---|
355 | };
|
---|
356 |
|
---|
357 | PRIVATE char *sstr_f8[] =
|
---|
358 | {
|
---|
359 | "inc\t", "dec\t", "call\t", "call\tfar ",
|
---|
360 | "jmp\t", "jmp\tfar ", "push\t", "???\t",
|
---|
361 | };
|
---|
362 |
|
---|
363 | PRIVATE int data_seg; /* data segment (munged name for asld) */
|
---|
364 | PRIVATE unsigned hasize; /* half address size in bits */
|
---|
365 | PRIVATE unsigned hdefsize;
|
---|
366 | PRIVATE unsigned hosize; /* half operand size in bits */
|
---|
367 | /* for easy index into reg tables */
|
---|
368 | PRIVATE opcode_pt mod;
|
---|
369 | PRIVATE off_t offtable[2];
|
---|
370 | PRIVATE off_t *offptr;
|
---|
371 | PRIVATE off_t *off1ptr;
|
---|
372 | PRIVATE opcode_pt reg;
|
---|
373 | PRIVATE opcode_pt rm;
|
---|
374 |
|
---|
375 | PRIVATE su8_pt get8s()
|
---|
376 | {
|
---|
377 | u8_t got;
|
---|
378 |
|
---|
379 | if ((got = get8()) > MAX_SIGNED_CHAR)
|
---|
380 | got -= (MAX_UNSIGNED_CHAR + 1);
|
---|
381 | return got;
|
---|
382 | }
|
---|
383 |
|
---|
384 | PRIVATE void getmodregrm()
|
---|
385 | {
|
---|
386 | opcode_pt modregrm;
|
---|
387 |
|
---|
388 | modregrm = get8();
|
---|
389 | mod = modregrm & MOD_MASK;
|
---|
390 | reg = (modregrm & REG_MASK) >> REG_SHIFT;
|
---|
391 | rm = (modregrm & RM_MASK) >> RM_SHIFT;
|
---|
392 | }
|
---|
393 |
|
---|
394 | PRIVATE void i_00_to_3f(opc)
|
---|
395 | opcode_pt opc;
|
---|
396 | {
|
---|
397 | opcode_pt sub;
|
---|
398 |
|
---|
399 | if (opc == 15)
|
---|
400 | pagef();
|
---|
401 | else if ((sub = opc & 7) >= 6)
|
---|
402 | {
|
---|
403 | outustr((sstr_00_to_3f - 6)[((opc >> 2) & 0x0E) + sub]);
|
---|
404 | if (!(opc & 1))
|
---|
405 | data_seg = opc;
|
---|
406 | }
|
---|
407 | else
|
---|
408 | {
|
---|
409 | oututstr(str_00_to_3f[(opc >> 3) & 7]);
|
---|
410 | if (sub == 4)
|
---|
411 | {
|
---|
412 | outustr(genreg[0]);
|
---|
413 | outcomma();
|
---|
414 | Ib();
|
---|
415 | }
|
---|
416 | else if (sub == 5)
|
---|
417 | {
|
---|
418 | outax();
|
---|
419 | outcomma();
|
---|
420 | Iv();
|
---|
421 | }
|
---|
422 | else
|
---|
423 | outad(sub);
|
---|
424 | }
|
---|
425 | }
|
---|
426 |
|
---|
427 | PRIVATE void i_40_to_5f(opc)
|
---|
428 | opcode_pt opc;
|
---|
429 | {
|
---|
430 | outustr(str_40_to_5f[(opc >> 3) & 3]);
|
---|
431 | outustr(genreg[hosize + (opc & 7)]);
|
---|
432 | }
|
---|
433 |
|
---|
434 | PRIVATE void i_60_to_6f(opc)
|
---|
435 | opcode_pt opc;
|
---|
436 | {
|
---|
437 | /* most for 386, some for 286 */
|
---|
438 |
|
---|
439 | outustr((str_60_to_6f - 0x60)[opc]);
|
---|
440 | switch (opc)
|
---|
441 | {
|
---|
442 | case 0x60:
|
---|
443 | case 0x61:
|
---|
444 | if (hosize == 16)
|
---|
445 | outwsize();
|
---|
446 | break;
|
---|
447 | case 0x62:
|
---|
448 | GvMa();
|
---|
449 | break;
|
---|
450 | case 0x63:
|
---|
451 | EwRw();
|
---|
452 | break;
|
---|
453 | case 0x64:
|
---|
454 | case 0x65:
|
---|
455 | data_seg = opc;
|
---|
456 | break;
|
---|
457 | case 0x66:
|
---|
458 | hosize = (16 + 8) - hdefsize;
|
---|
459 | break;
|
---|
460 | case 0x67:
|
---|
461 | hasize = (16 + 8) - hdefsize;
|
---|
462 | break;
|
---|
463 | case 0x68:
|
---|
464 | outword();
|
---|
465 | Iv();
|
---|
466 | break;
|
---|
467 | case 0x6A:
|
---|
468 | outword();
|
---|
469 | outimmed(SIGNBIT | WORDBIT);
|
---|
470 | break;
|
---|
471 | case 0x69:
|
---|
472 | GvEv();
|
---|
473 | outcomma();
|
---|
474 | Iv();
|
---|
475 | break;
|
---|
476 | case 0x6B:
|
---|
477 | GvEv();
|
---|
478 | outcomma();
|
---|
479 | outimmed(SIGNBIT | WORDBIT);
|
---|
480 | break;
|
---|
481 | case 0x6D:
|
---|
482 | case 0x6F:
|
---|
483 | outwsize();
|
---|
484 | break;
|
---|
485 | }
|
---|
486 | }
|
---|
487 |
|
---|
488 | PRIVATE void i_70_to_7f(opc)
|
---|
489 | opcode_pt opc;
|
---|
490 | {
|
---|
491 | outustr("j");
|
---|
492 | oututstr((str_flags - 0x70)[opc]);
|
---|
493 | Jb();
|
---|
494 | }
|
---|
495 |
|
---|
496 | PRIVATE void i_80(opc)
|
---|
497 | opcode_pt opc;
|
---|
498 | {
|
---|
499 | if (opc >= 4)
|
---|
500 | {
|
---|
501 | outustr(opc >= 6 ? "xchg\t" : "test\t");
|
---|
502 | outad(opc);
|
---|
503 | }
|
---|
504 | else
|
---|
505 | {
|
---|
506 | getmodregrm();
|
---|
507 | oututstr(str_00_to_3f[reg]);
|
---|
508 | outbwptr(opc);
|
---|
509 | outea(opc);
|
---|
510 | outcomma();
|
---|
511 | outimmed(opc);
|
---|
512 | #ifdef SIGNED_LOGICALS
|
---|
513 | if (opc & SIGNBIT && (reg == 1 || reg == 4 || reg == 6))
|
---|
514 | /* and, or and xor with signe extension are not documented in some
|
---|
515 | * 8086 and 80286 manuals, but make sense and work
|
---|
516 | */
|
---|
517 | outfishy();
|
---|
518 | #endif
|
---|
519 | }
|
---|
520 | }
|
---|
521 |
|
---|
522 | PRIVATE void i_88(opc)
|
---|
523 | opcode_pt opc;
|
---|
524 | {
|
---|
525 | if (opc < 4)
|
---|
526 | {
|
---|
527 | outustr(movtab);
|
---|
528 | outad(opc);
|
---|
529 | }
|
---|
530 | else if (opc == 5)
|
---|
531 | {
|
---|
532 | oututstr("lea");
|
---|
533 | GvM();
|
---|
534 | }
|
---|
535 | else if (opc == 7)
|
---|
536 | {
|
---|
537 | oututstr("pop");
|
---|
538 | getmodregrm();
|
---|
539 | outwptr();
|
---|
540 | Ev();
|
---|
541 | if (reg != 0)
|
---|
542 | outfishy();
|
---|
543 | }
|
---|
544 | else
|
---|
545 | {
|
---|
546 | getmodregrm();
|
---|
547 | outustr(movtab);
|
---|
548 | if (!(opc & TOREGBIT))
|
---|
549 | {
|
---|
550 | Ev();
|
---|
551 | outcomma();
|
---|
552 | }
|
---|
553 | outustr(segreg[reg]);
|
---|
554 | if (opc & TOREGBIT)
|
---|
555 | {
|
---|
556 | outcomma();
|
---|
557 | Ev();
|
---|
558 | }
|
---|
559 | }
|
---|
560 | }
|
---|
561 |
|
---|
562 | PRIVATE void i_90(opc)
|
---|
563 | opcode_pt opc;
|
---|
564 | {
|
---|
565 | if (opc == 0)
|
---|
566 | outustr("nop");
|
---|
567 | else
|
---|
568 | {
|
---|
569 | outustr("xchg\t");
|
---|
570 | outax();
|
---|
571 | outcomma();
|
---|
572 | outustr(genreg[hosize + opc]);
|
---|
573 | }
|
---|
574 | }
|
---|
575 |
|
---|
576 | PRIVATE void i_98(opc)
|
---|
577 | opcode_pt opc;
|
---|
578 | {
|
---|
579 | outustr((str_98 - 8)[opc + hosize]);
|
---|
580 | if (opc == 2)
|
---|
581 | outsegpc();
|
---|
582 | }
|
---|
583 |
|
---|
584 | PRIVATE void i_a0(opc)
|
---|
585 | opcode_pt opc;
|
---|
586 | {
|
---|
587 | outustr(str_a0[opc]);
|
---|
588 | if (opc < 4)
|
---|
589 | {
|
---|
590 | mod = MEM0_MOD; /* fake */
|
---|
591 | reg = 0; /* fake ax */
|
---|
592 | if (hasize == 16)
|
---|
593 | rm = 5; /* fake [d16] */
|
---|
594 | else
|
---|
595 | rm = 6; /* fake [d32] */
|
---|
596 | outad1(opc ^ TOREGBIT);
|
---|
597 | }
|
---|
598 | else if (opc & 1)
|
---|
599 | outwsize();
|
---|
600 | }
|
---|
601 |
|
---|
602 | PRIVATE void i_a8(opc)
|
---|
603 | opcode_pt opc;
|
---|
604 | {
|
---|
605 | outustr(str_a8[opc]);
|
---|
606 | if (opc < 2)
|
---|
607 | {
|
---|
608 | outalorx(opc);
|
---|
609 | outcomma();
|
---|
610 | outimmed(opc);
|
---|
611 | }
|
---|
612 | else if (opc & 1)
|
---|
613 | outwsize();
|
---|
614 | }
|
---|
615 |
|
---|
616 | PRIVATE void i_b0(opc)
|
---|
617 | opcode_pt opc;
|
---|
618 | {
|
---|
619 | outustr(movtab);
|
---|
620 | outustr(genreg[opc]);
|
---|
621 | outcomma();
|
---|
622 | Ib();
|
---|
623 | }
|
---|
624 |
|
---|
625 | PRIVATE void i_b8(opc)
|
---|
626 | opcode_pt opc;
|
---|
627 | {
|
---|
628 | outustr(movtab);
|
---|
629 | outustr(genreg[hosize + opc]);
|
---|
630 | outcomma();
|
---|
631 | Iv();
|
---|
632 | }
|
---|
633 |
|
---|
634 | PRIVATE void i_c0(opc)
|
---|
635 | opcode_pt opc;
|
---|
636 | {
|
---|
637 | outustr(str_c0[opc]);
|
---|
638 | if (opc >= 6)
|
---|
639 | {
|
---|
640 | getmodregrm();
|
---|
641 | outbwptr(opc);
|
---|
642 | outea(opc);
|
---|
643 | outcomma();
|
---|
644 | outimmed(opc & WORDBIT);
|
---|
645 | if (reg != 0)
|
---|
646 | /* not completely decoded (like DEBUG) */
|
---|
647 | outfishy();
|
---|
648 | }
|
---|
649 | else if (opc >= 4)
|
---|
650 | GvMp();
|
---|
651 | else if (opc == 2)
|
---|
652 | Iv();
|
---|
653 | else if (opc < 2)
|
---|
654 | shift(opc);
|
---|
655 | }
|
---|
656 |
|
---|
657 | PRIVATE void i_c8(opc)
|
---|
658 | opcode_pt opc;
|
---|
659 | {
|
---|
660 | outustr(str_c8[opc]);
|
---|
661 | if (opc == 0)
|
---|
662 | {
|
---|
663 | Iw();
|
---|
664 | outcomma();
|
---|
665 | Ib();
|
---|
666 | }
|
---|
667 | if (opc == 2)
|
---|
668 | Iv();
|
---|
669 | else if (opc == 5)
|
---|
670 | Ib();
|
---|
671 | else if (opc == 7 && hosize == 16)
|
---|
672 | outwsize();
|
---|
673 | }
|
---|
674 |
|
---|
675 | PRIVATE void i_d0(opc)
|
---|
676 | opcode_pt opc;
|
---|
677 | {
|
---|
678 | opcode_pt aabyte;
|
---|
679 |
|
---|
680 | if (opc < 4)
|
---|
681 | shift(opc | 0xD0);
|
---|
682 | else
|
---|
683 | {
|
---|
684 | outustr((str_d0 - 4)[opc]);
|
---|
685 | if (opc < 6 && (aabyte = get8()) != 0x0A)
|
---|
686 | {
|
---|
687 | outtab();
|
---|
688 | outh8(aabyte);
|
---|
689 | outfishy();
|
---|
690 | }
|
---|
691 | }
|
---|
692 | }
|
---|
693 |
|
---|
694 | PRIVATE void i_d8(opc)
|
---|
695 | opcode_pt opc;
|
---|
696 | {
|
---|
697 | opcode_pt esc;
|
---|
698 | char *str;
|
---|
699 |
|
---|
700 | getmodregrm();
|
---|
701 | esc = (opc << 3) | reg;
|
---|
702 | if ((str = (mod == REG_MOD ? str1_d8 : str_d8)[esc]) == NULL)
|
---|
703 | {
|
---|
704 | escape:
|
---|
705 | oututstr("esc");
|
---|
706 | outh8(esc);
|
---|
707 | outcomma();
|
---|
708 | outea(0);
|
---|
709 | return;
|
---|
710 | }
|
---|
711 | if (*str == 0)
|
---|
712 | {
|
---|
713 | str = sstr_d8[str[1] + rm];
|
---|
714 | if (str == NULL)
|
---|
715 | goto escape;
|
---|
716 | outustr(str);
|
---|
717 | return;
|
---|
718 | }
|
---|
719 | outustr(str);
|
---|
720 | outtab();
|
---|
721 | if (mod == REG_MOD)
|
---|
722 | {
|
---|
723 | if (opc == 0 && reg != 2 && reg != 3)
|
---|
724 | outustr("st,");
|
---|
725 | outf1();
|
---|
726 | if (opc == 4 || opc == 6)
|
---|
727 | outustr(",st");
|
---|
728 | return;
|
---|
729 | }
|
---|
730 | switch(size_d8[esc])
|
---|
731 | {
|
---|
732 | case 4:
|
---|
733 | outustr("d");
|
---|
734 | case 2:
|
---|
735 | outwptr();
|
---|
736 | break;
|
---|
737 | case 8:
|
---|
738 | outustr("q");
|
---|
739 | outwptr();
|
---|
740 | break;
|
---|
741 | case 10:
|
---|
742 | outustr("t");
|
---|
743 | outbptr();
|
---|
744 | break;
|
---|
745 | }
|
---|
746 | outea(opc);
|
---|
747 | }
|
---|
748 |
|
---|
749 | PRIVATE void i_e0(opc)
|
---|
750 | opcode_pt opc;
|
---|
751 | {
|
---|
752 | outustr(str_e0[opc]);
|
---|
753 | if (opc < 4)
|
---|
754 | Jb();
|
---|
755 | else if (opc < 6)
|
---|
756 | {
|
---|
757 | outalorx(opc);
|
---|
758 | outcomma();
|
---|
759 | Ib();
|
---|
760 | }
|
---|
761 | else
|
---|
762 | {
|
---|
763 | Ib();
|
---|
764 | outcomma();
|
---|
765 | outalorx(opc);
|
---|
766 | }
|
---|
767 | }
|
---|
768 |
|
---|
769 | PRIVATE void i_e8(opc)
|
---|
770 | opcode_pt opc;
|
---|
771 | {
|
---|
772 | outustr(str_e8[opc]);
|
---|
773 | if (opc < 2)
|
---|
774 | Jv();
|
---|
775 | else if (opc == 2)
|
---|
776 | outsegpc();
|
---|
777 | else if (opc == 3)
|
---|
778 | Jb();
|
---|
779 | else
|
---|
780 | {
|
---|
781 | if (opc & TOREGBIT)
|
---|
782 | {
|
---|
783 | outustr(genreg[10]);
|
---|
784 | outcomma();
|
---|
785 | outalorx(opc);
|
---|
786 | }
|
---|
787 | else
|
---|
788 | {
|
---|
789 | outalorx(opc);
|
---|
790 | outcomma();
|
---|
791 | outustr(genreg[10]);
|
---|
792 | }
|
---|
793 | }
|
---|
794 | }
|
---|
795 |
|
---|
796 | PRIVATE void i_f0(opc)
|
---|
797 | opcode_pt opc;
|
---|
798 | {
|
---|
799 | if (opc < 6)
|
---|
800 | outustr(str_f0[opc]);
|
---|
801 | else
|
---|
802 | {
|
---|
803 | getmodregrm();
|
---|
804 | outustr(sstr_f0[reg]);
|
---|
805 | outbwptr(opc);
|
---|
806 | outea(opc);
|
---|
807 | if (reg == 0)
|
---|
808 | {
|
---|
809 | outcomma();
|
---|
810 | outimmed(opc & WORDBIT);
|
---|
811 | }
|
---|
812 | }
|
---|
813 | }
|
---|
814 |
|
---|
815 | PRIVATE void i_f8(opc)
|
---|
816 | opcode_pt opc;
|
---|
817 | {
|
---|
818 | if (opc < 6)
|
---|
819 | outustr(str_f8[opc]);
|
---|
820 | else
|
---|
821 | {
|
---|
822 | getmodregrm();
|
---|
823 | if (opc == 6 && reg >= 2)
|
---|
824 | outustr("fishy\t");
|
---|
825 | else
|
---|
826 | outustr(sstr_f8[reg]);
|
---|
827 | outbwptr(opc);
|
---|
828 | outea(opc);
|
---|
829 | }
|
---|
830 | }
|
---|
831 |
|
---|
832 | PRIVATE void outad(opc)
|
---|
833 | opcode_pt opc;
|
---|
834 | {
|
---|
835 | getmodregrm();
|
---|
836 | outad1(opc);
|
---|
837 | }
|
---|
838 |
|
---|
839 | PRIVATE void outad1(opc)
|
---|
840 | opcode_pt opc;
|
---|
841 | {
|
---|
842 | if (!(opc & TOREGBIT))
|
---|
843 | {
|
---|
844 | outea(opc);
|
---|
845 | outcomma();
|
---|
846 | }
|
---|
847 | if (opc & WORDBIT)
|
---|
848 | Gv1();
|
---|
849 | else
|
---|
850 | outustr(genreg[reg]);
|
---|
851 | if (opc & TOREGBIT)
|
---|
852 | {
|
---|
853 | outcomma();
|
---|
854 | outea(opc);
|
---|
855 | }
|
---|
856 | }
|
---|
857 |
|
---|
858 | PRIVATE void outalorx(opc)
|
---|
859 | opcode_pt opc;
|
---|
860 | {
|
---|
861 | if (opc & WORDBIT)
|
---|
862 | outax();
|
---|
863 | else
|
---|
864 | outustr(genreg[0]);
|
---|
865 | }
|
---|
866 |
|
---|
867 | PRIVATE void outax()
|
---|
868 | {
|
---|
869 | outustr(genreg[hosize]);
|
---|
870 | }
|
---|
871 |
|
---|
872 | PRIVATE void outbptr()
|
---|
873 | {
|
---|
874 | outustr("byte ptr ");
|
---|
875 | }
|
---|
876 |
|
---|
877 | PRIVATE void outbwptr(opc)
|
---|
878 | opcode_pt opc;
|
---|
879 | {
|
---|
880 | if (mod != REG_MOD)
|
---|
881 | {
|
---|
882 | if (opc & WORDBIT)
|
---|
883 | outwptr();
|
---|
884 | else
|
---|
885 | outbptr();
|
---|
886 | }
|
---|
887 | }
|
---|
888 |
|
---|
889 | PRIVATE void outea(wordflags)
|
---|
890 | opcode_pt wordflags;
|
---|
891 | {
|
---|
892 | reg_pt base;
|
---|
893 | reg_pt index;
|
---|
894 | opcode_pt ss;
|
---|
895 | opcode_pt ssindexbase;
|
---|
896 |
|
---|
897 | if (mod == REG_MOD)
|
---|
898 | outustr(genreg[hosize * (wordflags & WORDBIT) + rm]);
|
---|
899 | else
|
---|
900 | {
|
---|
901 | outbyte(LINDIRECT);
|
---|
902 | if (hasize == 16)
|
---|
903 | {
|
---|
904 | if (rm == 4)
|
---|
905 | {
|
---|
906 | base = (ssindexbase = get8()) & BASE_MASK;
|
---|
907 | if (mod == MEM0_MOD && base == 5)
|
---|
908 | outgetaddr();
|
---|
909 | else
|
---|
910 | outustr((genreg + 16)[base]);
|
---|
911 | ss = (ssindexbase & SS_MASK) >> SS_SHIFT;
|
---|
912 | if ((index = (ssindexbase & INDEX_MASK) >> INDEX_SHIFT) != 4)
|
---|
913 | {
|
---|
914 | outbyte('+');
|
---|
915 | outustr((genreg + 16)[index]);
|
---|
916 | outstr("\0\0\0*2\0*4\0*8\0" + (3 * ss));
|
---|
917 | }
|
---|
918 | }
|
---|
919 | else if (mod == MEM0_MOD && rm == 5)
|
---|
920 | outgetaddr();
|
---|
921 | else
|
---|
922 | outustr((genreg + 16)[rm]);
|
---|
923 | }
|
---|
924 | else if (mod == MEM0_MOD && rm == 6)
|
---|
925 | outgetaddr();
|
---|
926 | else
|
---|
927 | outustr(indreg[rm]);
|
---|
928 | if (mod == MEM1_MOD)
|
---|
929 | /* fake sign extension to get +- */
|
---|
930 | outimmed(SIGNBIT | WORDBIT);
|
---|
931 | else if (mod == MEM2_MOD)
|
---|
932 | {
|
---|
933 | outbyte('+');
|
---|
934 | #if (_WORD_SIZE == 4)
|
---|
935 | out32offset();
|
---|
936 | #else
|
---|
937 | outgetaddr();
|
---|
938 | #endif
|
---|
939 | }
|
---|
940 | outbyte(RINDIRECT);
|
---|
941 | if (hasize == 16 && rm == 4 && index == 4 && ss != 0)
|
---|
942 | outfishy();
|
---|
943 | }
|
---|
944 | }
|
---|
945 |
|
---|
946 | PRIVATE void outf1()
|
---|
947 | {
|
---|
948 | outustr("st(");
|
---|
949 | outbyte((int) (rm + '0'));
|
---|
950 | outbyte(')');
|
---|
951 | }
|
---|
952 |
|
---|
953 | #if (_WORD_SIZE == 4)
|
---|
954 |
|
---|
955 | PRIVATE void out32offset()
|
---|
956 | {
|
---|
957 | off_t off;
|
---|
958 |
|
---|
959 | if (hasize == 16)
|
---|
960 | off = get32();
|
---|
961 | else
|
---|
962 | outfishy();
|
---|
963 |
|
---|
964 | outh32(off);
|
---|
965 | }
|
---|
966 | #endif
|
---|
967 |
|
---|
968 | PRIVATE void outfishy()
|
---|
969 | {
|
---|
970 | outustr("\t???");
|
---|
971 | }
|
---|
972 |
|
---|
973 | PRIVATE void outgetaddr()
|
---|
974 | {
|
---|
975 | off_t off;
|
---|
976 |
|
---|
977 | if (hasize == 16)
|
---|
978 | off = get32();
|
---|
979 | else
|
---|
980 | off = get16();
|
---|
981 |
|
---|
982 | if ( finds_data(off,data_seg) )
|
---|
983 | *offptr++ = off;
|
---|
984 | else if (hasize == 16)
|
---|
985 | outh32(off);
|
---|
986 | else
|
---|
987 | outh16((u16_t) off);
|
---|
988 | }
|
---|
989 |
|
---|
990 | PRIVATE void outimmed(signwordflag)
|
---|
991 | opcode_pt signwordflag;
|
---|
992 | {
|
---|
993 | su8_pt byte;
|
---|
994 |
|
---|
995 | if (signwordflag & WORDBIT)
|
---|
996 | {
|
---|
997 | if (signwordflag & SIGNBIT)
|
---|
998 | {
|
---|
999 | if ((byte = get8s()) < 0)
|
---|
1000 | {
|
---|
1001 | outbyte('-');
|
---|
1002 | byte = -byte;
|
---|
1003 | }
|
---|
1004 | else
|
---|
1005 | outbyte('+');
|
---|
1006 | outh8((u8_t) byte);
|
---|
1007 | }
|
---|
1008 | else
|
---|
1009 | Iv();
|
---|
1010 | }
|
---|
1011 | else
|
---|
1012 | Ib();
|
---|
1013 | }
|
---|
1014 |
|
---|
1015 | PRIVATE void outpc(pc)
|
---|
1016 | off_t pc;
|
---|
1017 | {
|
---|
1018 | if (hosize == 8)
|
---|
1019 | pc = (u16_t) pc;
|
---|
1020 |
|
---|
1021 | if ( finds_pc(pc) )
|
---|
1022 | *offptr++ = pc;
|
---|
1023 | else if (hosize == 16)
|
---|
1024 | outh32(pc);
|
---|
1025 | else
|
---|
1026 | outh16((u16_t) pc);
|
---|
1027 | }
|
---|
1028 |
|
---|
1029 | PRIVATE void outsegpc()
|
---|
1030 | {
|
---|
1031 | off_t oldbase;
|
---|
1032 | off_t pc;
|
---|
1033 |
|
---|
1034 | if (hosize == 16)
|
---|
1035 | pc = get32();
|
---|
1036 | else
|
---|
1037 | pc = get16();
|
---|
1038 | oldbase = uptr.base;
|
---|
1039 | outh16((u16_t) (uptr.base = get16())); /* fake seg for lookup of pc */
|
---|
1040 | /* TODO - convert to offset in protected mode */
|
---|
1041 | outbyte(':');
|
---|
1042 | outpc(pc);
|
---|
1043 | uptr.base = oldbase;
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 | PRIVATE void oututstr(s)
|
---|
1047 | char *s;
|
---|
1048 | {
|
---|
1049 | outustr(s);
|
---|
1050 | outtab();
|
---|
1051 | }
|
---|
1052 |
|
---|
1053 | PRIVATE void outword()
|
---|
1054 | {
|
---|
1055 | outustr("dword " + ((16 - hosize) >> 3));
|
---|
1056 | }
|
---|
1057 |
|
---|
1058 | PRIVATE void outwptr()
|
---|
1059 | {
|
---|
1060 | outword();
|
---|
1061 | outustr("ptr ");
|
---|
1062 | }
|
---|
1063 |
|
---|
1064 | PRIVATE void outwsize()
|
---|
1065 | {
|
---|
1066 | if (hosize == 16)
|
---|
1067 | outustr("d");
|
---|
1068 | else
|
---|
1069 | outustr("w");
|
---|
1070 | }
|
---|
1071 |
|
---|
1072 | PRIVATE void pagef()
|
---|
1073 | {
|
---|
1074 | opcode_pt opc;
|
---|
1075 | int regbad;
|
---|
1076 |
|
---|
1077 | if ((opc = get8()) <= 1 || opc == 0xBA)
|
---|
1078 | {
|
---|
1079 | if (opc == 0xBA)
|
---|
1080 | opc = 16;
|
---|
1081 | else
|
---|
1082 | opc *= 8;
|
---|
1083 | getmodregrm();
|
---|
1084 | outustr(ssstr_0f[opc += reg]);
|
---|
1085 | if (opc < 6 || opc == 12 || opc == 14)
|
---|
1086 | Ew();
|
---|
1087 | else if (opc >= 8 && opc < 13)
|
---|
1088 | Ms();
|
---|
1089 | else if (opc >= 20)
|
---|
1090 | {
|
---|
1091 | outbwptr(WORDBIT);
|
---|
1092 | EvIb();
|
---|
1093 | }
|
---|
1094 | }
|
---|
1095 | else if (opc < 4)
|
---|
1096 | {
|
---|
1097 | oututstr("lar\0lsl" + 4 * (opc - 2));
|
---|
1098 | GvEw();
|
---|
1099 | }
|
---|
1100 | else if (opc == 5)
|
---|
1101 | {
|
---|
1102 | outustr("loadall");
|
---|
1103 | outfishy();
|
---|
1104 | }
|
---|
1105 | else if (opc == 6)
|
---|
1106 | outustr("clts");
|
---|
1107 | else if (opc < 0x20)
|
---|
1108 | outstr(fishy);
|
---|
1109 | else if (opc < 0x27 && opc != 0x25)
|
---|
1110 | {
|
---|
1111 | outustr(movtab);
|
---|
1112 | getmodregrm();
|
---|
1113 | hosize = 16;
|
---|
1114 | if (!(opc & TOREGBIT))
|
---|
1115 | {
|
---|
1116 | Ev(); /* Rd() since hosize is 16 */
|
---|
1117 | outcomma();
|
---|
1118 | }
|
---|
1119 | regbad = FALSE;
|
---|
1120 | if (opc & 1)
|
---|
1121 | {
|
---|
1122 | outustr("dr");
|
---|
1123 | if (reg == 4 || reg == 5)
|
---|
1124 | regbad = TRUE;
|
---|
1125 | }
|
---|
1126 | else if (opc < 0x24)
|
---|
1127 | {
|
---|
1128 | outustr("cr");
|
---|
1129 | if (reg >= 4 || reg == 1)
|
---|
1130 | regbad = TRUE;
|
---|
1131 | }
|
---|
1132 | else
|
---|
1133 | {
|
---|
1134 | outustr("tr");
|
---|
1135 | if (reg < 6)
|
---|
1136 | regbad = TRUE;
|
---|
1137 | }
|
---|
1138 | outbyte((int) (reg + '0'));
|
---|
1139 | if (opc & TOREGBIT)
|
---|
1140 | {
|
---|
1141 | outcomma();
|
---|
1142 | Ev();
|
---|
1143 | }
|
---|
1144 | if (regbad || mod != REG_MOD)
|
---|
1145 | outfishy();
|
---|
1146 | }
|
---|
1147 | else if (opc < 0x80)
|
---|
1148 | outstr(fishy);
|
---|
1149 | else if (opc < 0x90)
|
---|
1150 | {
|
---|
1151 | outustr("j");
|
---|
1152 | oututstr((str_flags - 0x80)[opc]);
|
---|
1153 | Jv();
|
---|
1154 | }
|
---|
1155 | else if (opc < 0xA0)
|
---|
1156 | {
|
---|
1157 | outustr("set");
|
---|
1158 | oututstr((str_flags - 0x90)[opc]);
|
---|
1159 | getmodregrm();
|
---|
1160 | outbwptr(0);
|
---|
1161 | Eb();
|
---|
1162 | }
|
---|
1163 | else if (opc < 0xC0)
|
---|
1164 | {
|
---|
1165 | outustr((sstr_0f - 0xA0)[opc]);
|
---|
1166 | switch (opc)
|
---|
1167 | {
|
---|
1168 | case 0xA3:
|
---|
1169 | case 0xAB:
|
---|
1170 | case 0xB3:
|
---|
1171 | case 0xBB:
|
---|
1172 | EvGv();
|
---|
1173 | break;
|
---|
1174 | case 0xA4:
|
---|
1175 | case 0xAC:
|
---|
1176 | EvGv();
|
---|
1177 | outcomma();
|
---|
1178 | Ib();
|
---|
1179 | break;
|
---|
1180 | case 0xA5:
|
---|
1181 | case 0xAD:
|
---|
1182 | EvGv();
|
---|
1183 | outcomma();
|
---|
1184 | CL();
|
---|
1185 | break;
|
---|
1186 | case 0xAF:
|
---|
1187 | case 0xBC:
|
---|
1188 | case 0xBD:
|
---|
1189 | GvEv();
|
---|
1190 | break;
|
---|
1191 | case 0xB2:
|
---|
1192 | case 0xB4:
|
---|
1193 | case 0xB5:
|
---|
1194 | GvMp();
|
---|
1195 | break;
|
---|
1196 | case 0xB6:
|
---|
1197 | case 0xBE:
|
---|
1198 | Gv();
|
---|
1199 | outcomma();
|
---|
1200 | outbwptr(opc);
|
---|
1201 | Eb();
|
---|
1202 | break;
|
---|
1203 | case 0xB7:
|
---|
1204 | case 0xBF:
|
---|
1205 | Gv();
|
---|
1206 | outcomma();
|
---|
1207 | hosize = 8; /* done in Ew(), but too late */
|
---|
1208 | outbwptr(opc);
|
---|
1209 | Ew();
|
---|
1210 | break;
|
---|
1211 | }
|
---|
1212 | }
|
---|
1213 | else
|
---|
1214 | outstr(fishy);
|
---|
1215 | }
|
---|
1216 |
|
---|
1217 | PRIVATE int puti()
|
---|
1218 | {
|
---|
1219 | static int hadprefix;
|
---|
1220 | opcode_pt opcode;
|
---|
1221 |
|
---|
1222 | more:
|
---|
1223 | offptr = offtable;
|
---|
1224 | opcode = get8();
|
---|
1225 | if (!hadprefix)
|
---|
1226 | {
|
---|
1227 | data_seg = DSEG;
|
---|
1228 | hdefsize = 8;
|
---|
1229 | if (bits32)
|
---|
1230 | hdefsize = 16;
|
---|
1231 | hosize =
|
---|
1232 | hasize = hdefsize;
|
---|
1233 | }
|
---|
1234 | (*optable[opcode >> 3])(opcode < 0x80 ? opcode : opcode & 7);
|
---|
1235 | if (offptr > offtable)
|
---|
1236 | {
|
---|
1237 | if (stringtab() >= 31)
|
---|
1238 | {
|
---|
1239 | outspace();
|
---|
1240 | outspace();
|
---|
1241 | }
|
---|
1242 | else
|
---|
1243 | while (stringtab() < 32)
|
---|
1244 | outtab();
|
---|
1245 | outbyte(';');
|
---|
1246 | for (off1ptr = offtable; off1ptr < offptr; ++off1ptr)
|
---|
1247 | {
|
---|
1248 | outspace();
|
---|
1249 | if (*off1ptr < 0x10000)
|
---|
1250 | outh16((u16_t) *off1ptr);
|
---|
1251 | else
|
---|
1252 | outh32(*off1ptr);
|
---|
1253 | }
|
---|
1254 | offptr = offtable;
|
---|
1255 | }
|
---|
1256 | if ((opcode & 0xE7) == 0x26 ||
|
---|
1257 | opcode >= 0x64 && opcode < 0x68 ||
|
---|
1258 | opcode == 0xF0 || opcode == 0xF2 || opcode == 0xF3)
|
---|
1259 | /* not finished instruction for 0x26, 0x2E, 0x36, 0x3E seg overrides
|
---|
1260 | * and 0x64, 0x65 386 seg overrides
|
---|
1261 | * and 0x66, 0x67 386 size prefixes
|
---|
1262 | * and 0xF0 lock, 0xF2 repne, 0xF3 rep
|
---|
1263 | */
|
---|
1264 | {
|
---|
1265 | hadprefix = TRUE;
|
---|
1266 | goto more; /* TODO - print prefixes better */
|
---|
1267 | return FALSE;
|
---|
1268 | }
|
---|
1269 | hadprefix = FALSE;
|
---|
1270 | return TRUE;
|
---|
1271 | }
|
---|
1272 |
|
---|
1273 | PRIVATE void shift(opc)
|
---|
1274 | opcode_pt opc;
|
---|
1275 | {
|
---|
1276 | getmodregrm();
|
---|
1277 | oututstr(sstr_d0[reg]);
|
---|
1278 | outbwptr(opc);
|
---|
1279 | outea(opc);
|
---|
1280 | outcomma();
|
---|
1281 | if (opc < 0xD0)
|
---|
1282 | Ib();
|
---|
1283 | else if (opc & 2)
|
---|
1284 | CL();
|
---|
1285 | else
|
---|
1286 | outbyte('1');
|
---|
1287 | }
|
---|
1288 |
|
---|
1289 | PRIVATE void checkmemory()
|
---|
1290 | {
|
---|
1291 | if (mod == REG_MOD)
|
---|
1292 | outfishy();
|
---|
1293 | }
|
---|
1294 |
|
---|
1295 | PRIVATE void CL()
|
---|
1296 | {
|
---|
1297 | outustr(genreg[1]);
|
---|
1298 | }
|
---|
1299 |
|
---|
1300 | PRIVATE void Eb()
|
---|
1301 | {
|
---|
1302 | outea(0);
|
---|
1303 | }
|
---|
1304 |
|
---|
1305 | PRIVATE void Ev()
|
---|
1306 | {
|
---|
1307 | outea(WORDBIT);
|
---|
1308 | }
|
---|
1309 |
|
---|
1310 | PRIVATE void EvGv()
|
---|
1311 | {
|
---|
1312 | getmodregrm();
|
---|
1313 | Ev();
|
---|
1314 | outcomma();
|
---|
1315 | Gv1();
|
---|
1316 | }
|
---|
1317 |
|
---|
1318 | PRIVATE void EvIb()
|
---|
1319 | {
|
---|
1320 | Ev();
|
---|
1321 | outcomma();
|
---|
1322 | Ib();
|
---|
1323 | }
|
---|
1324 |
|
---|
1325 | PRIVATE void Ew()
|
---|
1326 | {
|
---|
1327 | hosize = 8;
|
---|
1328 | Ev();
|
---|
1329 | }
|
---|
1330 |
|
---|
1331 | PRIVATE void EwRw()
|
---|
1332 | {
|
---|
1333 | hosize = 8;
|
---|
1334 | EvGv();
|
---|
1335 | }
|
---|
1336 |
|
---|
1337 | PRIVATE void Gv()
|
---|
1338 | {
|
---|
1339 | getmodregrm();
|
---|
1340 | Gv1();
|
---|
1341 | }
|
---|
1342 |
|
---|
1343 | PRIVATE void Gv1()
|
---|
1344 | {
|
---|
1345 | outustr(genreg[hosize + reg]);
|
---|
1346 | }
|
---|
1347 |
|
---|
1348 | PRIVATE void GvEv()
|
---|
1349 | {
|
---|
1350 | Gv();
|
---|
1351 | outcomma();
|
---|
1352 | Ev();
|
---|
1353 | }
|
---|
1354 |
|
---|
1355 | PRIVATE void GvEw()
|
---|
1356 | {
|
---|
1357 | Gv();
|
---|
1358 | outcomma();
|
---|
1359 | Ew();
|
---|
1360 | }
|
---|
1361 |
|
---|
1362 | PRIVATE void GvM()
|
---|
1363 | {
|
---|
1364 | GvEv();
|
---|
1365 | checkmemory();
|
---|
1366 | }
|
---|
1367 |
|
---|
1368 | PRIVATE void GvMa()
|
---|
1369 | {
|
---|
1370 | GvM();
|
---|
1371 | }
|
---|
1372 |
|
---|
1373 | PRIVATE void GvMp()
|
---|
1374 | {
|
---|
1375 | GvM();
|
---|
1376 | }
|
---|
1377 |
|
---|
1378 | PRIVATE void Ib()
|
---|
1379 | {
|
---|
1380 | outh8(get8());
|
---|
1381 | }
|
---|
1382 |
|
---|
1383 | PRIVATE void Iw()
|
---|
1384 | {
|
---|
1385 | outh16(get16());
|
---|
1386 | }
|
---|
1387 |
|
---|
1388 | PRIVATE void Iv()
|
---|
1389 | {
|
---|
1390 | if (hosize == 16)
|
---|
1391 | outh32(get32());
|
---|
1392 | else
|
---|
1393 | Iw();
|
---|
1394 | }
|
---|
1395 |
|
---|
1396 | PRIVATE void Jb()
|
---|
1397 | {
|
---|
1398 | off_t pcjump;
|
---|
1399 |
|
---|
1400 | pcjump = get8s();
|
---|
1401 | outpc(pcjump + uptr.off);
|
---|
1402 | }
|
---|
1403 |
|
---|
1404 | PRIVATE void Jv()
|
---|
1405 | {
|
---|
1406 | off_t pcjump;
|
---|
1407 |
|
---|
1408 | if (hosize == 16)
|
---|
1409 | pcjump = get32();
|
---|
1410 | else
|
---|
1411 | pcjump = (su16_t) get16();
|
---|
1412 | outpc(pcjump + uptr.off);
|
---|
1413 | }
|
---|
1414 |
|
---|
1415 | PRIVATE void Ms()
|
---|
1416 | {
|
---|
1417 | Ev();
|
---|
1418 | checkmemory();
|
---|
1419 | }
|
---|
1420 |
|
---|
1421 | /********************* DASM ******************************/
|
---|
1422 |
|
---|
1423 | PUBLIC long dasm( addr, count, symflg )
|
---|
1424 | long addr;
|
---|
1425 | int count;
|
---|
1426 | int symflg;
|
---|
1427 | {
|
---|
1428 | #if (_WORD_SIZE == 4)
|
---|
1429 | bits32 = TRUE; /* Set mode */
|
---|
1430 | #else
|
---|
1431 | bits32 = FALSE;
|
---|
1432 | #endif
|
---|
1433 | uptr.off = addr;
|
---|
1434 | uptr.base = 0; /* not known */
|
---|
1435 | while ( count-- != 0 && show1instruction() )
|
---|
1436 | ;
|
---|
1437 | }
|
---|
1438 |
|
---|
1439 |
|
---|
1440 | PRIVATE int show1instruction()
|
---|
1441 | {
|
---|
1442 | register int column;
|
---|
1443 | int idone;
|
---|
1444 | static char line[81];
|
---|
1445 | int maxcol;
|
---|
1446 | struct address_s newuptr;
|
---|
1447 | struct address_s olduptr;
|
---|
1448 |
|
---|
1449 | outbyte('\r');
|
---|
1450 | do
|
---|
1451 | {
|
---|
1452 | if ( text_symbol(uptr.off) ) {
|
---|
1453 | outbyte(':');
|
---|
1454 | outbyte('\n');
|
---|
1455 | }
|
---|
1456 | olduptr = uptr;
|
---|
1457 | openstring(line);
|
---|
1458 | idone = puti();
|
---|
1459 | line[stringpos()] = 0;
|
---|
1460 | closestring();
|
---|
1461 | newuptr = uptr;
|
---|
1462 | uptr = olduptr;
|
---|
1463 | column = outssegaddr(&uptr);
|
---|
1464 | while (uptr.off != newuptr.off)
|
---|
1465 | {
|
---|
1466 | outh8(get8());
|
---|
1467 | column += 2;
|
---|
1468 | }
|
---|
1469 | maxcol = bits32 ? 24 : 16;
|
---|
1470 | while (column < maxcol)
|
---|
1471 | {
|
---|
1472 | outtab();
|
---|
1473 | column += 8;
|
---|
1474 | }
|
---|
1475 | outtab();
|
---|
1476 | outstr(line);
|
---|
1477 | outbyte('\n');
|
---|
1478 | }
|
---|
1479 | while (!idone); /* eat all prefixes */
|
---|
1480 | return TRUE;
|
---|
1481 | }
|
---|
1482 |
|
---|
1483 |
|
---|
1484 | PRIVATE u8_t get8()
|
---|
1485 | {
|
---|
1486 | /* get 8 bits current instruction pointer and advance pointer */
|
---|
1487 |
|
---|
1488 | u8_t temp;
|
---|
1489 |
|
---|
1490 | temp = peek_byte(uptr.off + uptr.base);
|
---|
1491 | ++uptr.off;
|
---|
1492 | return temp;
|
---|
1493 | }
|
---|
1494 |
|
---|
1495 | PRIVATE u16_t get16()
|
---|
1496 | {
|
---|
1497 | /* get 16 bits from current instruction pointer and advance pointer */
|
---|
1498 |
|
---|
1499 | u16_t temp;
|
---|
1500 |
|
---|
1501 | temp = peek_word(uptr.off + uptr.base);
|
---|
1502 | uptr.off += 2;
|
---|
1503 | return temp;
|
---|
1504 | }
|
---|
1505 |
|
---|
1506 | PRIVATE u32_t get32()
|
---|
1507 | {
|
---|
1508 | /* get 32 bits from current instruction pointer and advance pointer */
|
---|
1509 |
|
---|
1510 | u32_t temp;
|
---|
1511 |
|
---|
1512 | temp = peek_dword(uptr.off + uptr.base);
|
---|
1513 | uptr.off += 4;
|
---|
1514 | return temp;
|
---|
1515 | }
|
---|
1516 |
|
---|
1517 |
|
---|
1518 | PRIVATE int outsegaddr(addr)
|
---|
1519 | struct address_s *addr;
|
---|
1520 | {
|
---|
1521 | /* print segmented address */
|
---|
1522 |
|
---|
1523 | int bytes_printed;
|
---|
1524 |
|
---|
1525 | bytes_printed = 2;
|
---|
1526 | bytes_printed = outsegreg(addr->base);
|
---|
1527 | if (bytes_printed > 4)
|
---|
1528 | outbyte('+');
|
---|
1529 | else
|
---|
1530 | outbyte(':');
|
---|
1531 | ++bytes_printed;
|
---|
1532 | if (addr->off >= 0x10000)
|
---|
1533 | {
|
---|
1534 | outh32(addr->off);
|
---|
1535 | return bytes_printed + 8;
|
---|
1536 | }
|
---|
1537 | outh16((u16_t) addr->off);
|
---|
1538 | return bytes_printed + 4;
|
---|
1539 | }
|
---|
1540 |
|
---|
1541 | PRIVATE int outssegaddr(addr)
|
---|
1542 | struct address_s *addr;
|
---|
1543 | {
|
---|
1544 | /* print 32 bit segmented address and 2 spaces */
|
---|
1545 |
|
---|
1546 | int bytes_printed;
|
---|
1547 |
|
---|
1548 | bytes_printed = outsegaddr(addr);
|
---|
1549 | outspace();
|
---|
1550 | outspace();
|
---|
1551 | return bytes_printed + 2;
|
---|
1552 | }
|
---|
1553 |
|
---|
1554 | PRIVATE u8_t peek_byte(addr)
|
---|
1555 | off_t addr;
|
---|
1556 | {
|
---|
1557 | return (u8_t) peek_dword(addr) & 0xFF; /* 8 bits only */
|
---|
1558 | }
|
---|
1559 |
|
---|
1560 | PRIVATE u16_t peek_word(addr)
|
---|
1561 | off_t addr;
|
---|
1562 | {
|
---|
1563 | return (u16_t) peek_dword(addr);
|
---|
1564 | }
|
---|