source: trunk/minix/commands/mdb/mdbdis86.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 27.2 KB
Line 
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
12struct address_s
13{
14 off_t off;
15 off_t base;
16};
17
18PRIVATE int bits32;
19PRIVATE struct address_s uptr;
20
21FORWARD _PROTOTYPE( u8_t get8, (void) );
22FORWARD _PROTOTYPE( u16_t get16, (void) );
23FORWARD _PROTOTYPE( u32_t get32, (void) );
24FORWARD _PROTOTYPE( u8_t peek_byte, (off_t addr) );
25FORWARD _PROTOTYPE( u16_t peek_word, (off_t addr) );
26FORWARD _PROTOTYPE( int puti, (void) );
27FORWARD _PROTOTYPE( int outsegaddr, (struct address_s *addr) );
28FORWARD _PROTOTYPE( int outssegaddr, (struct address_s *addr) );
29FORWARD _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
59typedef unsigned opcode_pt; /* promote to unsigned and not int */
60
61typedef int reg_pt;
62typedef int su16_t;
63typedef int su8_pt;
64
65FORWARD _PROTOTYPE( su8_pt get8s , (void));
66FORWARD _PROTOTYPE( void getmodregrm , (void));
67FORWARD _PROTOTYPE( void i_00_to_3f , (opcode_pt opc ));
68FORWARD _PROTOTYPE( void i_40_to_5f , (opcode_pt opc ));
69FORWARD _PROTOTYPE( void i_60_to_6f , (opcode_pt opc ));
70FORWARD _PROTOTYPE( void i_70_to_7f , (opcode_pt opc ));
71FORWARD _PROTOTYPE( void i_80 , (opcode_pt opc ));
72FORWARD _PROTOTYPE( void i_88 , (opcode_pt opc ));
73FORWARD _PROTOTYPE( void i_90 , (opcode_pt opc ));
74FORWARD _PROTOTYPE( void i_98 , (opcode_pt opc ));
75FORWARD _PROTOTYPE( void i_a0 , (opcode_pt opc ));
76FORWARD _PROTOTYPE( void i_a8 , (opcode_pt opc ));
77FORWARD _PROTOTYPE( void i_b0 , (opcode_pt opc ));
78FORWARD _PROTOTYPE( void i_b8 , (opcode_pt opc ));
79FORWARD _PROTOTYPE( void i_c0 , (opcode_pt opc ));
80FORWARD _PROTOTYPE( void i_c8 , (opcode_pt opc ));
81FORWARD _PROTOTYPE( void i_d0 , (opcode_pt opc ));
82FORWARD _PROTOTYPE( void i_d8 , (opcode_pt opc ));
83FORWARD _PROTOTYPE( void i_e0 , (opcode_pt opc ));
84FORWARD _PROTOTYPE( void i_e8 , (opcode_pt opc ));
85FORWARD _PROTOTYPE( void i_f0 , (opcode_pt opc ));
86FORWARD _PROTOTYPE( void i_f8 , (opcode_pt opc ));
87FORWARD _PROTOTYPE( void outad , (opcode_pt opc ));
88FORWARD _PROTOTYPE( void outad1 , (opcode_pt opc ));
89FORWARD _PROTOTYPE( void outalorx , (opcode_pt opc ));
90FORWARD _PROTOTYPE( void outax , (void));
91FORWARD _PROTOTYPE( void outbptr , (void));
92FORWARD _PROTOTYPE( void outbwptr , (opcode_pt opc ));
93FORWARD _PROTOTYPE( void outea , (opcode_pt wordflags ));
94FORWARD _PROTOTYPE( void outf1 , (void));
95FORWARD _PROTOTYPE( void out32offset , (void));
96FORWARD _PROTOTYPE( void outfishy , (void));
97FORWARD _PROTOTYPE( void outgetaddr , (void));
98FORWARD _PROTOTYPE( void outimmed , (opcode_pt signwordflag ));
99FORWARD _PROTOTYPE( void outpc , (off_t pc ));
100FORWARD _PROTOTYPE( void outsegpc , (void));
101FORWARD _PROTOTYPE( void oututstr , (char *s ));
102FORWARD _PROTOTYPE( void outword , (void));
103FORWARD _PROTOTYPE( void outwptr , (void));
104FORWARD _PROTOTYPE( void outwsize , (void));
105FORWARD _PROTOTYPE( void pagef , (void));
106FORWARD _PROTOTYPE( void shift , (opcode_pt opc ));
107FORWARD _PROTOTYPE( void checkmemory , (void));
108FORWARD _PROTOTYPE( void CL , (void));
109FORWARD _PROTOTYPE( void Eb , (void));
110FORWARD _PROTOTYPE( void Ev , (void));
111FORWARD _PROTOTYPE( void EvGv , (void));
112FORWARD _PROTOTYPE( void EvIb , (void));
113FORWARD _PROTOTYPE( void Ew , (void));
114FORWARD _PROTOTYPE( void EwRw , (void));
115FORWARD _PROTOTYPE( void Gv , (void));
116FORWARD _PROTOTYPE( void Gv1 , (void));
117FORWARD _PROTOTYPE( void GvEv , (void));
118FORWARD _PROTOTYPE( void GvEw , (void));
119FORWARD _PROTOTYPE( void GvM , (void));
120FORWARD _PROTOTYPE( void GvMa , (void));
121FORWARD _PROTOTYPE( void GvMp , (void));
122FORWARD _PROTOTYPE( void Ib , (void));
123FORWARD _PROTOTYPE( void Iw , (void));
124FORWARD _PROTOTYPE( void Iv , (void));
125FORWARD _PROTOTYPE( void Jb , (void));
126FORWARD _PROTOTYPE( void Jv , (void));
127FORWARD _PROTOTYPE( void Ms , (void));
128
129_PROTOTYPE( typedef void (*pfv_t),(opcode_pt opc ));
130
131PRIVATE 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
167PRIVATE char fishy[] = "???";
168PRIVATE char movtab[] = "mov\t";
169
170PRIVATE 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
177PRIVATE char *segreg[] =
178{
179 "es", "cs", "ss", "ds", "fs", "gs", "?s", "?s",
180};
181
182PRIVATE char *indreg[] =
183{
184 "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx",
185};
186
187PRIVATE char *str_00_to_3f[] =
188{
189 /* index by (opcode >> 3) & 7 */
190 "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp",
191};
192
193PRIVATE 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
201PRIVATE 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
209PRIVATE 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
216PRIVATE char *str_40_to_5f[] =
217{
218 /* index by (opcode >> 3) & 3 */
219 "inc\t", "dec\t", "push\t", "pop\t",
220};
221
222PRIVATE 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
228PRIVATE 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
235PRIVATE 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
241PRIVATE char *str_a0[] =
242{
243 movtab, movtab, movtab, movtab, "movsb", "movs", "cmpsb", "cmps",
244};
245
246PRIVATE char *str_a8[] =
247{
248 "test\t", "test\t", "stosb", "stos", "lodsb", "lods", "scasb", "scas",
249};
250
251PRIVATE char *str_c0[] =
252{
253 "", "", "ret\t", "ret", "les\t", "lds\t", movtab, movtab,
254};
255
256PRIVATE char *str_c8[] =
257{
258 "enter\t", "leave", "retf\t", "retf", "int\t3", "int\t", "into", "iret",
259};
260
261PRIVATE char *str_d0[] =
262{
263 "aam", "aad", "db\td6", "xlat",
264};
265
266PRIVATE char *sstr_d0[] =
267{
268 "rol", "ror", "rcl", "rcr", "shl", "shr", fishy, "sar",
269};
270
271PRIVATE 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
283PRIVATE 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
295PRIVATE 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
303PRIVATE 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
325PRIVATE char *str_e0[] =
326{
327 "loopnz\t", "loopz\t", "loop\t", "jcxz\t",
328 "in\t", "in\t", "out\t", "out\t",
329};
330
331PRIVATE char *str_e8[] =
332{
333 "call\t", "jmp\t", "jmp\t", "jmp\t",
334 "in\t", "in\t", "out\t", "out\t",
335};
336
337PRIVATE char *str_f0[] =
338{
339 "lock\t", "db\tf1", "repnz\t", "repz\t",
340 "hlt", "cmc",
341 /* other 2 from sstr_f0 */
342};
343
344PRIVATE char *sstr_f0[] =
345{
346 "test\t", fishy, "not\t", "neg\t",
347 "mul\t", "imul\t", "div\t", "idiv\t",
348};
349
350PRIVATE char *str_f8[] =
351{
352 "clc", "stc", "cli", "sti",
353 "cld", "std",
354 /* other 2 from sstr_f8 */
355};
356
357PRIVATE char *sstr_f8[] =
358{
359 "inc\t", "dec\t", "call\t", "call\tfar ",
360 "jmp\t", "jmp\tfar ", "push\t", "???\t",
361};
362
363PRIVATE int data_seg; /* data segment (munged name for asld) */
364PRIVATE unsigned hasize; /* half address size in bits */
365PRIVATE unsigned hdefsize;
366PRIVATE unsigned hosize; /* half operand size in bits */
367 /* for easy index into reg tables */
368PRIVATE opcode_pt mod;
369PRIVATE off_t offtable[2];
370PRIVATE off_t *offptr;
371PRIVATE off_t *off1ptr;
372PRIVATE opcode_pt reg;
373PRIVATE opcode_pt rm;
374
375PRIVATE 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
384PRIVATE 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
394PRIVATE void i_00_to_3f(opc)
395opcode_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
427PRIVATE void i_40_to_5f(opc)
428opcode_pt opc;
429{
430 outustr(str_40_to_5f[(opc >> 3) & 3]);
431 outustr(genreg[hosize + (opc & 7)]);
432}
433
434PRIVATE void i_60_to_6f(opc)
435opcode_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
488PRIVATE void i_70_to_7f(opc)
489opcode_pt opc;
490{
491 outustr("j");
492 oututstr((str_flags - 0x70)[opc]);
493 Jb();
494}
495
496PRIVATE void i_80(opc)
497opcode_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
522PRIVATE void i_88(opc)
523opcode_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
562PRIVATE void i_90(opc)
563opcode_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
576PRIVATE void i_98(opc)
577opcode_pt opc;
578{
579 outustr((str_98 - 8)[opc + hosize]);
580 if (opc == 2)
581 outsegpc();
582}
583
584PRIVATE void i_a0(opc)
585opcode_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
602PRIVATE void i_a8(opc)
603opcode_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
616PRIVATE void i_b0(opc)
617opcode_pt opc;
618{
619 outustr(movtab);
620 outustr(genreg[opc]);
621 outcomma();
622 Ib();
623}
624
625PRIVATE void i_b8(opc)
626opcode_pt opc;
627{
628 outustr(movtab);
629 outustr(genreg[hosize + opc]);
630 outcomma();
631 Iv();
632}
633
634PRIVATE void i_c0(opc)
635opcode_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
657PRIVATE void i_c8(opc)
658opcode_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
675PRIVATE void i_d0(opc)
676opcode_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
694PRIVATE void i_d8(opc)
695opcode_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 {
704escape:
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
749PRIVATE void i_e0(opc)
750opcode_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
769PRIVATE void i_e8(opc)
770opcode_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
796PRIVATE void i_f0(opc)
797opcode_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
815PRIVATE void i_f8(opc)
816opcode_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
832PRIVATE void outad(opc)
833opcode_pt opc;
834{
835 getmodregrm();
836 outad1(opc);
837}
838
839PRIVATE void outad1(opc)
840opcode_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
858PRIVATE void outalorx(opc)
859opcode_pt opc;
860{
861 if (opc & WORDBIT)
862 outax();
863 else
864 outustr(genreg[0]);
865}
866
867PRIVATE void outax()
868{
869 outustr(genreg[hosize]);
870}
871
872PRIVATE void outbptr()
873{
874 outustr("byte ptr ");
875}
876
877PRIVATE void outbwptr(opc)
878opcode_pt opc;
879{
880 if (mod != REG_MOD)
881 {
882 if (opc & WORDBIT)
883 outwptr();
884 else
885 outbptr();
886 }
887}
888
889PRIVATE void outea(wordflags)
890opcode_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
946PRIVATE void outf1()
947{
948 outustr("st(");
949 outbyte((int) (rm + '0'));
950 outbyte(')');
951}
952
953#if (_WORD_SIZE == 4)
954
955PRIVATE 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
968PRIVATE void outfishy()
969{
970 outustr("\t???");
971}
972
973PRIVATE 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
990PRIVATE void outimmed(signwordflag)
991opcode_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
1015PRIVATE void outpc(pc)
1016off_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
1029PRIVATE 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
1046PRIVATE void oututstr(s)
1047char *s;
1048{
1049 outustr(s);
1050 outtab();
1051}
1052
1053PRIVATE void outword()
1054{
1055 outustr("dword " + ((16 - hosize) >> 3));
1056}
1057
1058PRIVATE void outwptr()
1059{
1060 outword();
1061 outustr("ptr ");
1062}
1063
1064PRIVATE void outwsize()
1065{
1066 if (hosize == 16)
1067 outustr("d");
1068 else
1069 outustr("w");
1070}
1071
1072PRIVATE 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
1217PRIVATE int puti()
1218{
1219 static int hadprefix;
1220 opcode_pt opcode;
1221
1222more:
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
1273PRIVATE void shift(opc)
1274opcode_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
1289PRIVATE void checkmemory()
1290{
1291 if (mod == REG_MOD)
1292 outfishy();
1293}
1294
1295PRIVATE void CL()
1296{
1297 outustr(genreg[1]);
1298}
1299
1300PRIVATE void Eb()
1301{
1302 outea(0);
1303}
1304
1305PRIVATE void Ev()
1306{
1307 outea(WORDBIT);
1308}
1309
1310PRIVATE void EvGv()
1311{
1312 getmodregrm();
1313 Ev();
1314 outcomma();
1315 Gv1();
1316}
1317
1318PRIVATE void EvIb()
1319{
1320 Ev();
1321 outcomma();
1322 Ib();
1323}
1324
1325PRIVATE void Ew()
1326{
1327 hosize = 8;
1328 Ev();
1329}
1330
1331PRIVATE void EwRw()
1332{
1333 hosize = 8;
1334 EvGv();
1335}
1336
1337PRIVATE void Gv()
1338{
1339 getmodregrm();
1340 Gv1();
1341}
1342
1343PRIVATE void Gv1()
1344{
1345 outustr(genreg[hosize + reg]);
1346}
1347
1348PRIVATE void GvEv()
1349{
1350 Gv();
1351 outcomma();
1352 Ev();
1353}
1354
1355PRIVATE void GvEw()
1356{
1357 Gv();
1358 outcomma();
1359 Ew();
1360}
1361
1362PRIVATE void GvM()
1363{
1364 GvEv();
1365 checkmemory();
1366}
1367
1368PRIVATE void GvMa()
1369{
1370 GvM();
1371}
1372
1373PRIVATE void GvMp()
1374{
1375 GvM();
1376}
1377
1378PRIVATE void Ib()
1379{
1380 outh8(get8());
1381}
1382
1383PRIVATE void Iw()
1384{
1385 outh16(get16());
1386}
1387
1388PRIVATE void Iv()
1389{
1390 if (hosize == 16)
1391 outh32(get32());
1392 else
1393 Iw();
1394}
1395
1396PRIVATE void Jb()
1397{
1398 off_t pcjump;
1399
1400 pcjump = get8s();
1401 outpc(pcjump + uptr.off);
1402}
1403
1404PRIVATE 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
1415PRIVATE void Ms()
1416{
1417 Ev();
1418 checkmemory();
1419}
1420
1421/********************* DASM ******************************/
1422
1423PUBLIC long dasm( addr, count, symflg )
1424long addr;
1425int count;
1426int 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
1440PRIVATE 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
1484PRIVATE 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
1495PRIVATE 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
1506PRIVATE 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
1518PRIVATE int outsegaddr(addr)
1519struct 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
1541PRIVATE int outssegaddr(addr)
1542struct 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
1554PRIVATE u8_t peek_byte(addr)
1555off_t addr;
1556{
1557 return (u8_t) peek_dword(addr) & 0xFF; /* 8 bits only */
1558}
1559
1560PRIVATE u16_t peek_word(addr)
1561off_t addr;
1562{
1563 return (u16_t) peek_dword(addr);
1564}
Note: See TracBrowser for help on using the repository browser.