vm: fix potential null deref
[minix.git] / commands / mdb / mdbdis86.c
blob5e7c8c0b357a8d58560335364fac985b00a67800
1 /*
2 * mdbdis86.c for mdb.c - 8086-386 and 8087 disassembler
3 * From Bruce Evans db
4 */
6 #include "mdb.h"
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <sys/types.h>
10 #include "proto.h"
12 struct address_s
14 off_t off;
15 off_t base;
18 static int bits32;
19 static struct address_s uptr;
21 static u8_t get8(void);
22 static u16_t get16(void);
23 static u32_t get32(void);
24 static u8_t peek_byte(off_t addr);
25 static u16_t peek_word(off_t addr);
26 static int puti(void);
27 static int outsegaddr(struct address_s *addr);
28 static int outssegaddr(struct address_s *addr);
29 static int show1instruction(void);
31 /************************* UNASM ******************************/
34 #define LINDIRECT '['
35 #define RINDIRECT ']'
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
52 #define SIGNBIT 0x02 /* opcode bits xxxxxxsw for immediates */
53 #define WORDBIT 0x01
54 #define TOREGBIT 0x02 /* opcode bit for non-immediates */
56 #define MAX_SIGNED_CHAR 0x7F /* will assume 2's complement */
57 #define MAX_UNSIGNED_CHAR 0xFF
59 typedef unsigned opcode_pt; /* promote to unsigned and not int */
61 typedef int reg_pt;
62 typedef int su16_t;
63 typedef int su8_pt;
65 static su8_pt get8s(void);
66 static void getmodregrm(void);
67 static void i_00_to_3f(opcode_pt opc );
68 static void i_40_to_5f(opcode_pt opc );
69 static void i_60_to_6f(opcode_pt opc );
70 static void i_70_to_7f(opcode_pt opc );
71 static void i_80(opcode_pt opc );
72 static void i_88(opcode_pt opc );
73 static void i_90(opcode_pt opc );
74 static void i_98(opcode_pt opc );
75 static void i_a0(opcode_pt opc );
76 static void i_a8(opcode_pt opc );
77 static void i_b0(opcode_pt opc );
78 static void i_b8(opcode_pt opc );
79 static void i_c0(opcode_pt opc );
80 static void i_c8(opcode_pt opc );
81 static void i_d0(opcode_pt opc );
82 static void i_d8(opcode_pt opc );
83 static void i_e0(opcode_pt opc );
84 static void i_e8(opcode_pt opc );
85 static void i_f0(opcode_pt opc );
86 static void i_f8(opcode_pt opc );
87 static void outad(opcode_pt opc );
88 static void outad1(opcode_pt opc );
89 static void outalorx(opcode_pt opc );
90 static void outax(void);
91 static void outbptr(void);
92 static void outbwptr(opcode_pt opc );
93 static void outea(opcode_pt wordflags );
94 static void outf1(void);
95 static void out32offset(void);
96 static void outfishy(void);
97 static void outgetaddr(void);
98 static void outimmed(opcode_pt signwordflag );
99 static void outpc(off_t pc );
100 static void outsegpc(void);
101 static void oututstr(char *s );
102 static void outword(void);
103 static void outwptr(void);
104 static void outwsize(void);
105 static void pagef(void);
106 static void shift(opcode_pt opc );
107 static void checkmemory(void);
108 static void CL(void);
109 static void Eb(void);
110 static void Ev(void);
111 static void EvGv(void);
112 static void EvIb(void);
113 static void Ew(void);
114 static void EwRw(void);
115 static void Gv(void);
116 static void Gv1(void);
117 static void GvEv(void);
118 static void GvEw(void);
119 static void GvM(void);
120 static void GvMa(void);
121 static void GvMp(void);
122 static void Ib(void);
123 static void Iw(void);
124 static void Iv(void);
125 static void Jb(void);
126 static void Jv(void);
127 static void Ms(void);
129 typedef void(*pfv_t) (opcode_pt opc );
131 static pfv_t optable[] =
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,
167 static char fishy[] = "???";
168 static char movtab[] = "mov\t";
170 static char *genreg[] =
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",
177 static char *segreg[] =
179 "es", "cs", "ss", "ds", "fs", "gs", "?s", "?s",
182 static char *indreg[] =
184 "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx",
187 static char *str_00_to_3f[] =
189 /* index by (opcode >> 3) & 7 */
190 "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp",
193 static char *sstr_00_to_3f[] =
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",
201 static char *sstr_0f[] =
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",
209 static char *ssstr_0f[] =
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",
216 static char *str_40_to_5f[] =
218 /* index by (opcode >> 3) & 3 */
219 "inc\t", "dec\t", "push\t", "pop\t",
222 static char *str_60_to_6f[] =
224 "pusha", "popa", "bound\t", "arpl\t", "fs:", "gs:", "os:", "as:",
225 "push\t", "imul\t", "push\t", "imul\t", "insb", "ins", "outsb", "outs",
228 static char *str_flags[] =
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",
235 static char *str_98[] =
237 "cbw", "cwd", "call\t", "wait", "pushf", "popf", "sahf", "lahf",
238 "cwde", "cdq", "call\t", "wait", "pushfd", "popfd", "sahf", "lahf",
241 static char *str_a0[] =
243 movtab, movtab, movtab, movtab, "movsb", "movs", "cmpsb", "cmps",
246 static char *str_a8[] =
248 "test\t", "test\t", "stosb", "stos", "lodsb", "lods", "scasb", "scas",
251 static char *str_c0[] =
253 "", "", "ret\t", "ret", "les\t", "lds\t", movtab, movtab,
256 static char *str_c8[] =
258 "enter\t", "leave", "retf\t", "retf", "int\t3", "int\t", "into", "iret",
261 static char *str_d0[] =
263 "aam", "aad", "db\td6", "xlat",
266 static char *sstr_d0[] =
268 "rol", "ror", "rcl", "rcr", "shl", "shr", fishy, "sar",
271 static char *str_d8[] =
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",
283 static char *str1_d8[] =
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,
295 static unsigned char size_d8[] =
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,
303 static char *sstr_d8[] =
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,
325 static char *str_e0[] =
327 "loopnz\t", "loopz\t", "loop\t", "jcxz\t",
328 "in\t", "in\t", "out\t", "out\t",
331 static char *str_e8[] =
333 "call\t", "jmp\t", "jmp\t", "jmp\t",
334 "in\t", "in\t", "out\t", "out\t",
337 static char *str_f0[] =
339 "lock\t", "db\tf1", "repnz\t", "repz\t",
340 "hlt", "cmc",
341 /* other 2 from sstr_f0 */
344 static char *sstr_f0[] =
346 "test\t", fishy, "not\t", "neg\t",
347 "mul\t", "imul\t", "div\t", "idiv\t",
350 static char *str_f8[] =
352 "clc", "stc", "cli", "sti",
353 "cld", "std",
354 /* other 2 from sstr_f8 */
357 static char *sstr_f8[] =
359 "inc\t", "dec\t", "call\t", "call\tfar ",
360 "jmp\t", "jmp\tfar ", "push\t", "???\t",
363 static int data_seg; /* data segment (munged name for asld) */
364 static unsigned hasize; /* half address size in bits */
365 static unsigned hdefsize;
366 static unsigned hosize; /* half operand size in bits */
367 /* for easy index into reg tables */
368 static opcode_pt mod;
369 static off_t offtable[2];
370 static off_t *offptr;
371 static off_t *off1ptr;
372 static opcode_pt reg;
373 static opcode_pt rm;
375 static su8_pt get8s()
377 su8_pt got;
379 if ((got = get8()) > MAX_SIGNED_CHAR)
380 got -= (MAX_UNSIGNED_CHAR + 1);
381 return got;
384 static void getmodregrm()
386 opcode_pt modregrm;
388 modregrm = get8();
389 mod = modregrm & MOD_MASK;
390 reg = (modregrm & REG_MASK) >> REG_SHIFT;
391 rm = (modregrm & RM_MASK) >> RM_SHIFT;
394 static void i_00_to_3f(opc)
395 opcode_pt opc;
397 opcode_pt sub;
399 if (opc == 15)
400 pagef();
401 else if ((sub = opc & 7) >= 6)
403 outustr((sstr_00_to_3f - 6)[((opc >> 2) & 0x0E) + sub]);
404 if (!(opc & 1))
405 data_seg = opc;
407 else
409 oututstr(str_00_to_3f[(opc >> 3) & 7]);
410 if (sub == 4)
412 outustr(genreg[0]);
413 outcomma();
414 Ib();
416 else if (sub == 5)
418 outax();
419 outcomma();
420 Iv();
422 else
423 outad(sub);
427 static void i_40_to_5f(opc)
428 opcode_pt opc;
430 outustr(str_40_to_5f[(opc >> 3) & 3]);
431 outustr(genreg[hosize + (opc & 7)]);
434 static void i_60_to_6f(opc)
435 opcode_pt opc;
437 /* most for 386, some for 286 */
439 outustr((str_60_to_6f - 0x60)[opc]);
440 switch (opc)
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;
488 static void i_70_to_7f(opc)
489 opcode_pt opc;
491 outustr("j");
492 oututstr((str_flags - 0x70)[opc]);
493 Jb();
496 static void i_80(opc)
497 opcode_pt opc;
499 if (opc >= 4)
501 outustr(opc >= 6 ? "xchg\t" : "test\t");
502 outad(opc);
504 else
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
517 outfishy();
518 #endif
522 static void i_88(opc)
523 opcode_pt opc;
525 if (opc < 4)
527 outustr(movtab);
528 outad(opc);
530 else if (opc == 5)
532 oututstr("lea");
533 GvM();
535 else if (opc == 7)
537 oututstr("pop");
538 getmodregrm();
539 outwptr();
540 Ev();
541 if (reg != 0)
542 outfishy();
544 else
546 getmodregrm();
547 outustr(movtab);
548 if (!(opc & TOREGBIT))
550 Ev();
551 outcomma();
553 outustr(segreg[reg]);
554 if (opc & TOREGBIT)
556 outcomma();
557 Ev();
562 static void i_90(opc)
563 opcode_pt opc;
565 if (opc == 0)
566 outustr("nop");
567 else
569 outustr("xchg\t");
570 outax();
571 outcomma();
572 outustr(genreg[hosize + opc]);
576 static void i_98(opc)
577 opcode_pt opc;
579 outustr((str_98 - 8)[opc + hosize]);
580 if (opc == 2)
581 outsegpc();
584 static void i_a0(opc)
585 opcode_pt opc;
587 outustr(str_a0[opc]);
588 if (opc < 4)
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);
598 else if (opc & 1)
599 outwsize();
602 static void i_a8(opc)
603 opcode_pt opc;
605 outustr(str_a8[opc]);
606 if (opc < 2)
608 outalorx(opc);
609 outcomma();
610 outimmed(opc);
612 else if (opc & 1)
613 outwsize();
616 static void i_b0(opc)
617 opcode_pt opc;
619 outustr(movtab);
620 outustr(genreg[opc]);
621 outcomma();
622 Ib();
625 static void i_b8(opc)
626 opcode_pt opc;
628 outustr(movtab);
629 outustr(genreg[hosize + opc]);
630 outcomma();
631 Iv();
634 static void i_c0(opc)
635 opcode_pt opc;
637 outustr(str_c0[opc]);
638 if (opc >= 6)
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();
649 else if (opc >= 4)
650 GvMp();
651 else if (opc == 2)
652 Iv();
653 else if (opc < 2)
654 shift(opc);
657 static void i_c8(opc)
658 opcode_pt opc;
660 outustr(str_c8[opc]);
661 if (opc == 0)
663 Iw();
664 outcomma();
665 Ib();
667 if (opc == 2)
668 Iv();
669 else if (opc == 5)
670 Ib();
671 else if (opc == 7 && hosize == 16)
672 outwsize();
675 static void i_d0(opc)
676 opcode_pt opc;
678 opcode_pt aabyte;
680 if (opc < 4)
681 shift(opc | 0xD0);
682 else
684 outustr((str_d0 - 4)[opc]);
685 if (opc < 6 && (aabyte = get8()) != 0x0A)
687 outtab();
688 outh8(aabyte);
689 outfishy();
694 static void i_d8(opc)
695 opcode_pt opc;
697 opcode_pt esc;
698 char *str;
700 getmodregrm();
701 esc = (opc << 3) | reg;
702 if ((str = (mod == REG_MOD ? str1_d8 : str_d8)[esc]) == NULL)
704 escape:
705 oututstr("esc");
706 outh8(esc);
707 outcomma();
708 outea(0);
709 return;
711 if (*str == 0)
713 str = sstr_d8[str[1] + rm];
714 if (str == NULL)
715 goto escape;
716 outustr(str);
717 return;
719 outustr(str);
720 outtab();
721 if (mod == REG_MOD)
723 if (opc == 0 && reg != 2 && reg != 3)
724 outustr("st,");
725 outf1();
726 if (opc == 4 || opc == 6)
727 outustr(",st");
728 return;
730 switch(size_d8[esc])
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;
746 outea(opc);
749 static void i_e0(opc)
750 opcode_pt opc;
752 outustr(str_e0[opc]);
753 if (opc < 4)
754 Jb();
755 else if (opc < 6)
757 outalorx(opc);
758 outcomma();
759 Ib();
761 else
763 Ib();
764 outcomma();
765 outalorx(opc);
769 static void i_e8(opc)
770 opcode_pt opc;
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
781 if (opc & TOREGBIT)
783 outustr(genreg[10]);
784 outcomma();
785 outalorx(opc);
787 else
789 outalorx(opc);
790 outcomma();
791 outustr(genreg[10]);
796 static void i_f0(opc)
797 opcode_pt opc;
799 if (opc < 6)
800 outustr(str_f0[opc]);
801 else
803 getmodregrm();
804 outustr(sstr_f0[reg]);
805 outbwptr(opc);
806 outea(opc);
807 if (reg == 0)
809 outcomma();
810 outimmed(opc & WORDBIT);
815 static void i_f8(opc)
816 opcode_pt opc;
818 if (opc < 6)
819 outustr(str_f8[opc]);
820 else
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);
832 static void outad(opc)
833 opcode_pt opc;
835 getmodregrm();
836 outad1(opc);
839 static void outad1(opc)
840 opcode_pt opc;
842 if (!(opc & TOREGBIT))
844 outea(opc);
845 outcomma();
847 if (opc & WORDBIT)
848 Gv1();
849 else
850 outustr(genreg[reg]);
851 if (opc & TOREGBIT)
853 outcomma();
854 outea(opc);
858 static void outalorx(opc)
859 opcode_pt opc;
861 if (opc & WORDBIT)
862 outax();
863 else
864 outustr(genreg[0]);
867 static void outax()
869 outustr(genreg[hosize]);
872 static void outbptr()
874 outustr("byte ptr ");
877 static void outbwptr(opc)
878 opcode_pt opc;
880 if (mod != REG_MOD)
882 if (opc & WORDBIT)
883 outwptr();
884 else
885 outbptr();
889 static void outea(wordflags)
890 opcode_pt wordflags;
892 reg_pt base;
893 reg_pt index;
894 opcode_pt ss;
895 opcode_pt ssindexbase;
897 if (mod == REG_MOD)
898 outustr(genreg[hosize * (wordflags & WORDBIT) + rm]);
899 else
901 outbyte(LINDIRECT);
902 if (hasize == 16)
904 if (rm == 4)
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)
914 outbyte('+');
915 outustr((genreg + 16)[index]);
916 outstr("\0\0\0*2\0*4\0*8\0" + (3 * ss));
919 else if (mod == MEM0_MOD && rm == 5)
920 outgetaddr();
921 else
922 outustr((genreg + 16)[rm]);
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)
933 outbyte('+');
934 out32offset();
936 outbyte(RINDIRECT);
937 if (hasize == 16 && rm == 4 && index == 4 && ss != 0)
938 outfishy();
942 static void outf1()
944 outustr("st(");
945 outbyte((int) (rm + '0'));
946 outbyte(')');
949 static void out32offset()
951 off_t off;
953 if (hasize == 16)
954 off = get32();
955 else
956 outfishy();
958 outh32(off);
961 static void outfishy()
963 outustr("\t???");
966 static void outgetaddr()
968 off_t off;
970 if (hasize == 16)
971 off = get32();
972 else
973 off = get16();
975 if ( finds_data(off,data_seg) )
976 *offptr++ = off;
977 else if (hasize == 16)
978 outh32(off);
979 else
980 outh16((u16_t) off);
983 static void outimmed(signwordflag)
984 opcode_pt signwordflag;
986 su8_pt byte;
988 if (signwordflag & WORDBIT)
990 if (signwordflag & SIGNBIT)
992 if ((byte = get8s()) < 0)
994 outbyte('-');
995 byte = -byte;
997 else
998 outbyte('+');
999 outh8((u8_t) byte);
1001 else
1002 Iv();
1004 else
1005 Ib();
1008 static void outpc(pc)
1009 off_t pc;
1011 if (hosize == 8)
1012 pc = (u16_t) pc;
1014 if ( finds_pc(pc) )
1015 *offptr++ = pc;
1016 else if (hosize == 16)
1017 outh32(pc);
1018 else
1019 outh16((u16_t) pc);
1022 static void outsegpc()
1024 off_t oldbase;
1025 off_t pc;
1027 if (hosize == 16)
1028 pc = get32();
1029 else
1030 pc = get16();
1031 oldbase = uptr.base;
1032 outh16((u16_t) (uptr.base = get16())); /* fake seg for lookup of pc */
1033 /* TODO - convert to offset in protected mode */
1034 outbyte(':');
1035 outpc(pc);
1036 uptr.base = oldbase;
1039 static void oututstr(s)
1040 char *s;
1042 outustr(s);
1043 outtab();
1046 static void outword()
1048 outustr("dword " + ((16 - hosize) >> 3));
1051 static void outwptr()
1053 outword();
1054 outustr("ptr ");
1057 static void outwsize()
1059 if (hosize == 16)
1060 outustr("d");
1061 else
1062 outustr("w");
1065 static void pagef()
1067 opcode_pt opc;
1068 int regbad;
1070 if ((opc = get8()) <= 1 || opc == 0xBA)
1072 if (opc == 0xBA)
1073 opc = 16;
1074 else
1075 opc *= 8;
1076 getmodregrm();
1077 outustr(ssstr_0f[opc += reg]);
1078 if (opc < 6 || opc == 12 || opc == 14)
1079 Ew();
1080 else if (opc >= 8 && opc < 13)
1081 Ms();
1082 else if (opc >= 20)
1084 outbwptr(WORDBIT);
1085 EvIb();
1088 else if (opc < 4)
1090 oututstr("lar\0lsl" + 4 * (opc - 2));
1091 GvEw();
1093 else if (opc == 5)
1095 outustr("loadall");
1096 outfishy();
1098 else if (opc == 6)
1099 outustr("clts");
1100 else if (opc < 0x20)
1101 outstr(fishy);
1102 else if (opc < 0x27 && opc != 0x25)
1104 outustr(movtab);
1105 getmodregrm();
1106 hosize = 16;
1107 if (!(opc & TOREGBIT))
1109 Ev(); /* Rd() since hosize is 16 */
1110 outcomma();
1112 regbad = FALSE;
1113 if (opc & 1)
1115 outustr("dr");
1116 if (reg == 4 || reg == 5)
1117 regbad = TRUE;
1119 else if (opc < 0x24)
1121 outustr("cr");
1122 if (reg >= 4 || reg == 1)
1123 regbad = TRUE;
1125 else
1127 outustr("tr");
1128 if (reg < 6)
1129 regbad = TRUE;
1131 outbyte((int) (reg + '0'));
1132 if (opc & TOREGBIT)
1134 outcomma();
1135 Ev();
1137 if (regbad || mod != REG_MOD)
1138 outfishy();
1140 else if (opc < 0x80)
1141 outstr(fishy);
1142 else if (opc < 0x90)
1144 outustr("j");
1145 oututstr((str_flags - 0x80)[opc]);
1146 Jv();
1148 else if (opc < 0xA0)
1150 outustr("set");
1151 oututstr((str_flags - 0x90)[opc]);
1152 getmodregrm();
1153 outbwptr(0);
1154 Eb();
1156 else if (opc < 0xC0)
1158 outustr((sstr_0f - 0xA0)[opc]);
1159 switch (opc)
1161 case 0xA3:
1162 case 0xAB:
1163 case 0xB3:
1164 case 0xBB:
1165 EvGv();
1166 break;
1167 case 0xA4:
1168 case 0xAC:
1169 EvGv();
1170 outcomma();
1171 Ib();
1172 break;
1173 case 0xA5:
1174 case 0xAD:
1175 EvGv();
1176 outcomma();
1177 CL();
1178 break;
1179 case 0xAF:
1180 case 0xBC:
1181 case 0xBD:
1182 GvEv();
1183 break;
1184 case 0xB2:
1185 case 0xB4:
1186 case 0xB5:
1187 GvMp();
1188 break;
1189 case 0xB6:
1190 case 0xBE:
1191 Gv();
1192 outcomma();
1193 outbwptr(opc);
1194 Eb();
1195 break;
1196 case 0xB7:
1197 case 0xBF:
1198 Gv();
1199 outcomma();
1200 hosize = 8; /* done in Ew(), but too late */
1201 outbwptr(opc);
1202 Ew();
1203 break;
1206 else
1207 outstr(fishy);
1210 static int puti()
1212 static int hadprefix;
1213 opcode_pt opcode;
1215 more:
1216 offptr = offtable;
1217 opcode = get8();
1218 if (!hadprefix)
1220 data_seg = DSEG;
1221 hdefsize = 8;
1222 if (bits32)
1223 hdefsize = 16;
1224 hosize =
1225 hasize = hdefsize;
1227 (*optable[opcode >> 3])(opcode < 0x80 ? opcode : opcode & 7);
1228 if (offptr > offtable)
1230 if (stringtab() >= 31)
1232 outspace();
1233 outspace();
1235 else
1236 while (stringtab() < 32)
1237 outtab();
1238 outbyte(';');
1239 for (off1ptr = offtable; off1ptr < offptr; ++off1ptr)
1241 outspace();
1242 if (*off1ptr < 0x10000)
1243 outh16((u16_t) *off1ptr);
1244 else
1245 outh32(*off1ptr);
1247 offptr = offtable;
1249 if ((opcode & 0xE7) == 0x26 ||
1250 opcode >= 0x64 && opcode < 0x68 ||
1251 opcode == 0xF0 || opcode == 0xF2 || opcode == 0xF3)
1252 /* not finished instruction for 0x26, 0x2E, 0x36, 0x3E seg overrides
1253 * and 0x64, 0x65 386 seg overrides
1254 * and 0x66, 0x67 386 size prefixes
1255 * and 0xF0 lock, 0xF2 repne, 0xF3 rep
1258 hadprefix = TRUE;
1259 goto more; /* TODO - print prefixes better */
1260 return FALSE;
1262 hadprefix = FALSE;
1263 return TRUE;
1266 static void shift(opc)
1267 opcode_pt opc;
1269 getmodregrm();
1270 oututstr(sstr_d0[reg]);
1271 outbwptr(opc);
1272 outea(opc);
1273 outcomma();
1274 if (opc < 0xD0)
1275 Ib();
1276 else if (opc & 2)
1277 CL();
1278 else
1279 outbyte('1');
1282 static void checkmemory()
1284 if (mod == REG_MOD)
1285 outfishy();
1288 static void CL()
1290 outustr(genreg[1]);
1293 static void Eb()
1295 outea(0);
1298 static void Ev()
1300 outea(WORDBIT);
1303 static void EvGv()
1305 getmodregrm();
1306 Ev();
1307 outcomma();
1308 Gv1();
1311 static void EvIb()
1313 Ev();
1314 outcomma();
1315 Ib();
1318 static void Ew()
1320 hosize = 8;
1321 Ev();
1324 static void EwRw()
1326 hosize = 8;
1327 EvGv();
1330 static void Gv()
1332 getmodregrm();
1333 Gv1();
1336 static void Gv1()
1338 outustr(genreg[hosize + reg]);
1341 static void GvEv()
1343 Gv();
1344 outcomma();
1345 Ev();
1348 static void GvEw()
1350 Gv();
1351 outcomma();
1352 Ew();
1355 static void GvM()
1357 GvEv();
1358 checkmemory();
1361 static void GvMa()
1363 GvM();
1366 static void GvMp()
1368 GvM();
1371 static void Ib()
1373 outh8(get8());
1376 static void Iw()
1378 outh16(get16());
1381 static void Iv()
1383 if (hosize == 16)
1384 outh32(get32());
1385 else
1386 Iw();
1389 static void Jb()
1391 off_t pcjump;
1393 pcjump = get8s();
1394 outpc(pcjump + uptr.off);
1397 static void Jv()
1399 off_t pcjump;
1401 if (hosize == 16)
1402 pcjump = get32();
1403 else
1404 pcjump = (su16_t) get16();
1405 outpc(pcjump + uptr.off);
1408 static void Ms()
1410 Ev();
1411 checkmemory();
1414 /********************* DASM ******************************/
1416 long dasm( addr, count, symflg )
1417 long addr;
1418 int count;
1419 int symflg;
1421 bits32 = TRUE; /* Set mode */
1422 uptr.off = addr;
1423 uptr.base = 0; /* not known */
1424 while ( count-- != 0 && show1instruction() )
1429 static int show1instruction()
1431 register int column;
1432 int idone;
1433 static char line[81];
1434 int maxcol;
1435 struct address_s newuptr;
1436 struct address_s olduptr;
1438 outbyte('\r');
1441 if ( text_symbol(uptr.off) ) {
1442 outbyte(':');
1443 outbyte('\n');
1445 olduptr = uptr;
1446 openstring(line);
1447 idone = puti();
1448 line[stringpos()] = 0;
1449 closestring();
1450 newuptr = uptr;
1451 uptr = olduptr;
1452 column = outssegaddr(&uptr);
1453 while (uptr.off != newuptr.off)
1455 outh8(get8());
1456 column += 2;
1458 maxcol = bits32 ? 24 : 16;
1459 while (column < maxcol)
1461 outtab();
1462 column += 8;
1464 outtab();
1465 outstr(line);
1466 outbyte('\n');
1468 while (!idone); /* eat all prefixes */
1469 return TRUE;
1473 static u8_t get8()
1475 /* get 8 bits current instruction pointer and advance pointer */
1477 u8_t temp;
1479 temp = peek_byte(uptr.off + uptr.base);
1480 ++uptr.off;
1481 return temp;
1484 static u16_t get16()
1486 /* get 16 bits from current instruction pointer and advance pointer */
1488 u16_t temp;
1490 temp = peek_word(uptr.off + uptr.base);
1491 uptr.off += 2;
1492 return temp;
1495 static u32_t get32()
1497 /* get 32 bits from current instruction pointer and advance pointer */
1499 u32_t temp;
1501 temp = peek_dword(uptr.off + uptr.base);
1502 uptr.off += 4;
1503 return temp;
1507 static int outsegaddr(addr)
1508 struct address_s *addr;
1510 /* print segmented address */
1512 int bytes_printed;
1514 bytes_printed = 2;
1515 bytes_printed = outsegreg(addr->base);
1516 if (bytes_printed > 4)
1517 outbyte('+');
1518 else
1519 outbyte(':');
1520 ++bytes_printed;
1521 if (addr->off >= 0x10000)
1523 outh32(addr->off);
1524 return bytes_printed + 8;
1526 outh16((u16_t) addr->off);
1527 return bytes_printed + 4;
1530 static int outssegaddr(addr)
1531 struct address_s *addr;
1533 /* print 32 bit segmented address and 2 spaces */
1535 int bytes_printed;
1537 bytes_printed = outsegaddr(addr);
1538 outspace();
1539 outspace();
1540 return bytes_printed + 2;
1543 static u8_t peek_byte(addr)
1544 off_t addr;
1546 return (u8_t) peek_dword(addr) & 0xFF; /* 8 bits only */
1549 static u16_t peek_word(addr)
1550 off_t addr;
1552 return (u16_t) peek_dword(addr);