mdbdis86.c

Go to the documentation of this file.
00001 /* 
00002  * mdbdis86.c for mdb.c - 8086-386 and 8087 disassembler
00003  * From Bruce Evans db
00004  */
00005 
00006 #include "mdb.h"
00007 #include <stddef.h>
00008 #include <stdio.h>
00009 #include <sys/types.h>
00010 #include "proto.h"
00011 
00012 struct address_s
00013 {
00014     off_t off;
00015     off_t base;
00016 };
00017 
00018 PRIVATE int bits32;
00019 PRIVATE struct address_s uptr;
00020 
00021 FORWARD _PROTOTYPE( u8_t  get8, (void) );
00022 FORWARD _PROTOTYPE( u16_t get16, (void) );
00023 FORWARD _PROTOTYPE( u32_t get32, (void) );
00024 FORWARD _PROTOTYPE( u8_t  peek_byte,  (off_t addr) );
00025 FORWARD _PROTOTYPE( u16_t peek_word,  (off_t addr) );
00026 FORWARD _PROTOTYPE( int puti, (void) );
00027 FORWARD _PROTOTYPE( int outsegaddr, (struct address_s *addr) );
00028 FORWARD _PROTOTYPE( int outssegaddr, (struct address_s *addr) );
00029 FORWARD _PROTOTYPE( int show1instruction , (void));
00030 
00031 /************************* UNASM ******************************/
00032 
00033 
00034 #define LINDIRECT       '['
00035 #define RINDIRECT       ']'
00036 
00037 #define BASE_MASK       0x07
00038 #define INDEX_MASK      0x38
00039 #define INDEX_SHIFT     3
00040 #define MOD_MASK        0xC0    /* mod reg r/m  is  mmrrrRRR */
00041 #define REG_MOD         0xC0
00042 #define MEM0_MOD        0x00
00043 #define MEM1_MOD        0x40
00044 #define MEM2_MOD        0x80
00045 #define REG_MASK        0x38
00046 #define REG_SHIFT       3
00047 #define RM_MASK         0x07
00048 #define RM_SHIFT        0
00049 #define SS_MASK         0xC0
00050 #define SS_SHIFT        6
00051 
00052 #define SIGNBIT         0x02    /* opcode bits xxxxxxsw for immediates */
00053 #define WORDBIT         0x01
00054 #define TOREGBIT        0x02    /* opcode bit for non-immediates */
00055 
00056 #define MAX_SIGNED_CHAR 0x7F    /* will assume 2's complement */
00057 #define MAX_UNSIGNED_CHAR       0xFF
00058 
00059 typedef unsigned opcode_pt;     /* promote to unsigned and not int */
00060 
00061 typedef int reg_pt;
00062 typedef int su16_t;
00063 typedef int su8_pt;
00064 
00065 FORWARD _PROTOTYPE(  su8_pt get8s , (void));
00066 FORWARD _PROTOTYPE(  void getmodregrm , (void));
00067 FORWARD _PROTOTYPE(  void i_00_to_3f , (opcode_pt opc ));
00068 FORWARD _PROTOTYPE(  void i_40_to_5f , (opcode_pt opc ));
00069 FORWARD _PROTOTYPE(  void i_60_to_6f , (opcode_pt opc ));
00070 FORWARD _PROTOTYPE(  void i_70_to_7f , (opcode_pt opc ));
00071 FORWARD _PROTOTYPE(  void i_80 , (opcode_pt opc ));
00072 FORWARD _PROTOTYPE(  void i_88 , (opcode_pt opc ));
00073 FORWARD _PROTOTYPE(  void i_90 , (opcode_pt opc ));
00074 FORWARD _PROTOTYPE(  void i_98 , (opcode_pt opc ));
00075 FORWARD _PROTOTYPE(  void i_a0 , (opcode_pt opc ));
00076 FORWARD _PROTOTYPE(  void i_a8 , (opcode_pt opc ));
00077 FORWARD _PROTOTYPE(  void i_b0 , (opcode_pt opc ));
00078 FORWARD _PROTOTYPE(  void i_b8 , (opcode_pt opc ));
00079 FORWARD _PROTOTYPE(  void i_c0 , (opcode_pt opc ));
00080 FORWARD _PROTOTYPE(  void i_c8 , (opcode_pt opc ));
00081 FORWARD _PROTOTYPE(  void i_d0 , (opcode_pt opc ));
00082 FORWARD _PROTOTYPE(  void i_d8 , (opcode_pt opc ));
00083 FORWARD _PROTOTYPE(  void i_e0 , (opcode_pt opc ));
00084 FORWARD _PROTOTYPE(  void i_e8 , (opcode_pt opc ));
00085 FORWARD _PROTOTYPE(  void i_f0 , (opcode_pt opc ));
00086 FORWARD _PROTOTYPE(  void i_f8 , (opcode_pt opc ));
00087 FORWARD _PROTOTYPE(  void outad , (opcode_pt opc ));
00088 FORWARD _PROTOTYPE(  void outad1 , (opcode_pt opc ));
00089 FORWARD _PROTOTYPE(  void outalorx , (opcode_pt opc ));
00090 FORWARD _PROTOTYPE(  void outax , (void));
00091 FORWARD _PROTOTYPE(  void outbptr , (void));
00092 FORWARD _PROTOTYPE(  void outbwptr , (opcode_pt opc ));
00093 FORWARD _PROTOTYPE(  void outea , (opcode_pt wordflags ));
00094 FORWARD _PROTOTYPE(  void outf1 , (void));
00095 FORWARD _PROTOTYPE(  void out32offset , (void));
00096 FORWARD _PROTOTYPE(  void outfishy , (void));
00097 FORWARD _PROTOTYPE(  void outgetaddr , (void));
00098 FORWARD _PROTOTYPE(  void outimmed , (opcode_pt signwordflag ));
00099 FORWARD _PROTOTYPE(  void outpc , (off_t pc ));
00100 FORWARD _PROTOTYPE(  void outsegpc , (void));
00101 FORWARD _PROTOTYPE(  void oututstr , (char *s ));
00102 FORWARD _PROTOTYPE(  void outword , (void));
00103 FORWARD _PROTOTYPE(  void outwptr , (void));
00104 FORWARD _PROTOTYPE(  void outwsize , (void));
00105 FORWARD _PROTOTYPE(  void pagef , (void));
00106 FORWARD _PROTOTYPE(  void shift , (opcode_pt opc ));
00107 FORWARD _PROTOTYPE(  void checkmemory , (void));
00108 FORWARD _PROTOTYPE(  void CL , (void));
00109 FORWARD _PROTOTYPE(  void Eb , (void));
00110 FORWARD _PROTOTYPE(  void Ev , (void));
00111 FORWARD _PROTOTYPE(  void EvGv , (void));
00112 FORWARD _PROTOTYPE(  void EvIb , (void));
00113 FORWARD _PROTOTYPE(  void Ew , (void));
00114 FORWARD _PROTOTYPE(  void EwRw , (void));
00115 FORWARD _PROTOTYPE(  void Gv , (void));
00116 FORWARD _PROTOTYPE(  void Gv1 , (void));
00117 FORWARD _PROTOTYPE(  void GvEv , (void));
00118 FORWARD _PROTOTYPE(  void GvEw , (void));
00119 FORWARD _PROTOTYPE(  void GvM , (void));
00120 FORWARD _PROTOTYPE(  void GvMa , (void));
00121 FORWARD _PROTOTYPE(  void GvMp , (void));
00122 FORWARD _PROTOTYPE(  void Ib , (void));
00123 FORWARD _PROTOTYPE(  void Iw , (void));
00124 FORWARD _PROTOTYPE(  void Iv , (void));
00125 FORWARD _PROTOTYPE(  void Jb , (void));
00126 FORWARD _PROTOTYPE(  void Jv , (void));
00127 FORWARD _PROTOTYPE(  void Ms , (void));
00128 
00129 _PROTOTYPE( typedef void (*pfv_t),(opcode_pt opc ));
00130 
00131 PRIVATE pfv_t optable[] =
00132 {
00133  i_00_to_3f,
00134  i_00_to_3f,
00135  i_00_to_3f,
00136  i_00_to_3f,
00137  i_00_to_3f,
00138  i_00_to_3f,
00139  i_00_to_3f,
00140  i_00_to_3f,
00141  i_40_to_5f,
00142  i_40_to_5f,
00143  i_40_to_5f,
00144  i_40_to_5f,
00145  i_60_to_6f,
00146  i_60_to_6f,
00147  i_70_to_7f,
00148  i_70_to_7f,
00149  i_80,
00150  i_88,
00151  i_90,
00152  i_98,
00153  i_a0,
00154  i_a8,
00155  i_b0,
00156  i_b8,
00157  i_c0,
00158  i_c8,
00159  i_d0,
00160  i_d8,
00161  i_e0,
00162  i_e8,
00163  i_f0,
00164  i_f8,
00165 };
00166 
00167 PRIVATE char fishy[] = "???";
00168 PRIVATE char movtab[] = "mov\t";
00169 
00170 PRIVATE char *genreg[] =
00171 {
00172  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
00173  "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
00174  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
00175 };
00176 
00177 PRIVATE char *segreg[] =
00178 {
00179  "es", "cs", "ss", "ds", "fs", "gs", "?s", "?s",
00180 };
00181 
00182 PRIVATE char *indreg[] =
00183 {
00184  "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx",
00185 };
00186 
00187 PRIVATE char *str_00_to_3f[] =
00188 {
00189  /* index by (opcode >> 3) & 7 */
00190  "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp",
00191 };
00192 
00193 PRIVATE char *sstr_00_to_3f[] =
00194 {
00195  /* index ((opc>>2) & 0x0E) + (opc & 7) - 6 */
00196  "push\tes", "pop\tes", "push\tcs", "pop\tcs",
00197  "push\tss", "pop\tss", "push\tds", "pop\tds",
00198  "es:", "daa", "cs:", "das", "ss:", "aaa", "ds:", "aas",
00199 };
00200 
00201 PRIVATE char *sstr_0f[] =
00202 {
00203  "push\tfs", "pop\tfs", fishy, "bt\t", "shld\t", "shld\t", fishy, fishy,
00204  "push\tgs", "pop\tgs", fishy, "bts\t", "shrd\t", "shrd\t", fishy, "imul\t",
00205  fishy, fishy, "lss\t", "btr\t", "lfs\t", "lgs\t", "movzx\t", "movzx\t",
00206  fishy, fishy, "", "btc\t", "bsf\t", "bsr\t", "movsx\t", "movsx\t",
00207 };
00208 
00209 PRIVATE char *ssstr_0f[] =
00210 {
00211  "sldt\t", "str\t", "lldt\t", "ltr\t", "verr\t", "verw\t", fishy, fishy,
00212  "sgdt\t", "sidt\t", "lgdt\t", "lidt\t", "smsw\t", fishy, "lmsw\t", fishy,
00213  fishy, fishy, fishy, fishy, "bt\t", "bts\t", "btr\t", "btc\t",
00214 };
00215 
00216 PRIVATE char *str_40_to_5f[] =
00217 {
00218  /* index by (opcode >> 3) & 3 */
00219  "inc\t", "dec\t", "push\t", "pop\t",
00220 };
00221 
00222 PRIVATE char *str_60_to_6f[] =
00223 {
00224  "pusha", "popa", "bound\t", "arpl\t", "fs:", "gs:", "os:", "as:",
00225  "push\t", "imul\t", "push\t", "imul\t", "insb", "ins", "outsb", "outs",
00226 };
00227 
00228 PRIVATE char *str_flags[] =
00229 {
00230  /* opcodes 0x70 to 0x7F, and 0x0F80 to 0x0F9F */
00231  "o", "no", "b", "nb", "z", "nz", "be", "a",
00232  "s", "ns", "pe", "po", "l", "ge", "le", "g",
00233 };
00234 
00235 PRIVATE char *str_98[] =
00236 {
00237  "cbw", "cwd", "call\t", "wait", "pushf", "popf", "sahf", "lahf",
00238  "cwde", "cdq", "call\t", "wait", "pushfd", "popfd", "sahf", "lahf",
00239 };
00240 
00241 PRIVATE char *str_a0[] =
00242 {
00243  movtab, movtab, movtab, movtab, "movsb", "movs", "cmpsb", "cmps",
00244 };
00245 
00246 PRIVATE char *str_a8[] =
00247 {
00248  "test\t", "test\t", "stosb", "stos", "lodsb", "lods", "scasb", "scas",
00249 };
00250 
00251 PRIVATE char *str_c0[] =
00252 {
00253  "", "", "ret\t", "ret", "les\t", "lds\t", movtab, movtab,
00254 };
00255 
00256 PRIVATE char *str_c8[] =
00257 {
00258  "enter\t", "leave", "retf\t", "retf", "int\t3", "int\t", "into", "iret",
00259 };
00260 
00261 PRIVATE char *str_d0[] =
00262 {
00263  "aam", "aad", "db\td6", "xlat",
00264 };
00265 
00266 PRIVATE char *sstr_d0[] =
00267 {
00268  "rol", "ror", "rcl", "rcr", "shl", "shr", fishy, "sar",
00269 };
00270 
00271 PRIVATE char *str_d8[] =
00272 {
00273  "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
00274  "fld", NULL, "fst", "fstp", "fldenv", "fldcw", "fstenv", "fstcw",
00275  "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr",
00276  "fild", NULL, "fist", "fistp", NULL, "fld", NULL, "fstp",
00277  "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
00278  "fld", NULL, "fst", "fstp", "frstor", NULL, "fsave", "fstsw",
00279  "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr",
00280  "fild", NULL, "fist", "fistp", "fbld", "fild", "fbstp", "fistp",
00281 };
00282 
00283 PRIVATE char *str1_d8[] =
00284 {
00285  "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
00286  "fld", "fxch", "\0\0", NULL, "\0\10", "\0\20", "\0\30", "\0\40",
00287  NULL, NULL, NULL, NULL, NULL, "\0\50", NULL, NULL,
00288  NULL, NULL, NULL, NULL, "\0\60", NULL, NULL, NULL,
00289  "fadd", "fmul", NULL, NULL, "fsubr", "fsub", "fdivr", "fdiv",
00290  "ffree", NULL, "fst", "fstp", "fucom", "fucomp", NULL, NULL,
00291  "faddp", "fmulp", NULL, "\0\70", "fsubrp", "fsubp", "fdivrp", "fdivp",
00292  NULL, NULL, NULL, NULL, "\0\100", NULL, NULL, NULL,
00293 };
00294 
00295 PRIVATE unsigned char size_d8[] =
00296 {
00297  4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 14-28, 2, 14-28, 2,
00298  4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 0, 10, 0, 10,
00299  8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 8, 8, 94-108, 0, 94-108, 2,
00300  2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 10, 8, 10, 8,
00301 };
00302 
00303 PRIVATE char *sstr_d8[] =
00304 {
00305  "fnop", NULL, NULL, NULL,                      /* D9D0 */
00306  NULL, NULL, NULL, NULL,
00307  "fchs", "fabs", NULL, NULL,                    /* D9E0 */
00308  "ftst", "fxam", NULL, NULL,
00309  "fld1", "fldl2t", "fldl2e", "fldpi",           /* D9E8 */
00310  "fldlg2", "fldln2", "fldz", NULL,
00311  "f2xm1", "fyl2x", "fptan", "fpatan",           /* D9F0 */
00312  "fxtract", "fprem1", "fdecstp", "fincstp",
00313  "fprem", "fyl2xp1", "fsqrt", "fsincos",        /* D9F8 */
00314  "frndint", "fscale", "fsin", "fcos",
00315  NULL, "fucompp", NULL, NULL,                   /* DAE8 */
00316  NULL, NULL, NULL, NULL,
00317  "feni", "fdisi", "fclex", "finit",             /* DBE0 */
00318  "fsetpm", NULL, NULL, NULL,
00319  NULL, "fcompp", NULL, NULL,                    /* DED8 */
00320  NULL, NULL, NULL, NULL,
00321  NULL, NULL, NULL, NULL,                        /* DFE0 */
00322  "fstsw\tax", NULL, NULL, NULL,
00323 };
00324 
00325 PRIVATE char *str_e0[] =
00326 {
00327  "loopnz\t", "loopz\t", "loop\t", "jcxz\t",
00328  "in\t", "in\t", "out\t", "out\t",
00329 };
00330 
00331 PRIVATE char *str_e8[] =
00332 {
00333  "call\t", "jmp\t", "jmp\t", "jmp\t",
00334  "in\t", "in\t", "out\t", "out\t",
00335 };
00336 
00337 PRIVATE char *str_f0[] =
00338 {
00339  "lock\t", "db\tf1", "repnz\t", "repz\t",
00340  "hlt", "cmc",
00341  /* other 2 from sstr_f0 */
00342 };
00343 
00344 PRIVATE char *sstr_f0[] =
00345 {
00346  "test\t", fishy, "not\t", "neg\t",
00347  "mul\t", "imul\t", "div\t", "idiv\t",
00348 };
00349 
00350 PRIVATE char *str_f8[] =
00351 {
00352  "clc", "stc", "cli", "sti",
00353  "cld", "std",
00354  /* other 2 from sstr_f8 */
00355 };
00356 
00357 PRIVATE char *sstr_f8[] =
00358 {
00359  "inc\t", "dec\t", "call\t", "call\tfar ",
00360  "jmp\t", "jmp\tfar ", "push\t", "???\t",
00361 };
00362 
00363 PRIVATE int data_seg;           /* data segment (munged name for asld) */
00364 PRIVATE unsigned hasize;        /* half address size in bits */
00365 PRIVATE unsigned hdefsize;
00366 PRIVATE unsigned hosize;        /* half operand size in bits */
00367                                 /* for easy index into reg tables */
00368 PRIVATE opcode_pt mod;
00369 PRIVATE off_t offtable[2];
00370 PRIVATE off_t *offptr;
00371 PRIVATE off_t *off1ptr;
00372 PRIVATE opcode_pt reg;
00373 PRIVATE opcode_pt rm;
00374 
00375 PRIVATE su8_pt get8s()
00376 {
00377     u8_t got;
00378 
00379     if ((got = get8()) > MAX_SIGNED_CHAR)
00380         got -= (MAX_UNSIGNED_CHAR + 1);
00381     return got;
00382 }
00383 
00384 PRIVATE void getmodregrm()
00385 {
00386     opcode_pt modregrm;
00387     
00388     modregrm = get8();
00389     mod = modregrm & MOD_MASK;
00390     reg = (modregrm & REG_MASK) >> REG_SHIFT;
00391     rm = (modregrm & RM_MASK) >> RM_SHIFT;
00392 }
00393 
00394 PRIVATE void i_00_to_3f(opc)
00395 opcode_pt opc;
00396 {
00397     opcode_pt sub;
00398     
00399     if (opc == 15)
00400         pagef();
00401     else if ((sub = opc & 7) >= 6)
00402     {
00403         outustr((sstr_00_to_3f - 6)[((opc >> 2) & 0x0E) + sub]);
00404         if (!(opc & 1))
00405             data_seg = opc;
00406     }
00407     else
00408     {
00409         oututstr(str_00_to_3f[(opc >> 3) & 7]);
00410         if (sub == 4)
00411         {
00412             outustr(genreg[0]);
00413             outcomma();
00414             Ib();
00415         }
00416         else if (sub == 5)
00417         {
00418             outax();
00419             outcomma();
00420             Iv();
00421         }
00422         else
00423             outad(sub);
00424     }
00425 }
00426 
00427 PRIVATE void i_40_to_5f(opc)
00428 opcode_pt opc;
00429 {
00430     outustr(str_40_to_5f[(opc >> 3) & 3]);
00431     outustr(genreg[hosize + (opc & 7)]);
00432 }
00433 
00434 PRIVATE void i_60_to_6f(opc)
00435 opcode_pt opc;
00436 {
00437 /* most for 386, some for 286 */
00438 
00439     outustr((str_60_to_6f - 0x60)[opc]);
00440     switch (opc)
00441     {
00442     case 0x60:
00443     case 0x61:
00444         if (hosize == 16)
00445             outwsize();
00446         break;
00447     case 0x62:
00448         GvMa();
00449         break;
00450     case 0x63:
00451         EwRw();
00452         break;
00453     case 0x64:
00454     case 0x65:
00455         data_seg = opc;
00456         break;
00457     case 0x66:
00458         hosize = (16 + 8) - hdefsize;
00459         break;
00460     case 0x67:
00461         hasize = (16 + 8) - hdefsize;
00462         break;
00463     case 0x68:
00464         outword();
00465         Iv();
00466         break;
00467     case 0x6A:
00468         outword();
00469         outimmed(SIGNBIT | WORDBIT);
00470         break;
00471     case 0x69:
00472         GvEv();
00473         outcomma();
00474         Iv();
00475         break;
00476     case 0x6B:
00477         GvEv();
00478         outcomma();
00479         outimmed(SIGNBIT | WORDBIT);
00480         break;
00481     case 0x6D:
00482     case 0x6F:
00483         outwsize();
00484         break;
00485     }
00486 }
00487 
00488 PRIVATE void i_70_to_7f(opc)
00489 opcode_pt opc;
00490 {
00491     outustr("j");
00492     oututstr((str_flags - 0x70)[opc]);
00493     Jb();
00494 }
00495 
00496 PRIVATE void i_80(opc)
00497 opcode_pt opc;
00498 {
00499     if (opc >= 4)
00500     {
00501         outustr(opc >= 6 ? "xchg\t" : "test\t");
00502         outad(opc);
00503     }
00504     else
00505     {
00506         getmodregrm();
00507         oututstr(str_00_to_3f[reg]);
00508         outbwptr(opc);
00509         outea(opc);
00510         outcomma();
00511         outimmed(opc);
00512 #ifdef SIGNED_LOGICALS
00513         if (opc & SIGNBIT && (reg == 1 || reg == 4 || reg == 6))
00514             /* and, or and xor with signe extension are not documented in some
00515              * 8086 and 80286 manuals, but make sense and work
00516              */
00517             outfishy();
00518 #endif
00519     }
00520 }
00521 
00522 PRIVATE void i_88(opc)
00523 opcode_pt opc;
00524 {
00525     if (opc < 4)
00526     {
00527         outustr(movtab);
00528         outad(opc);
00529     }
00530     else if (opc == 5)
00531     {
00532         oututstr("lea");
00533         GvM();
00534     }
00535     else if (opc == 7)
00536     {
00537         oututstr("pop");
00538         getmodregrm();
00539         outwptr();
00540         Ev();
00541         if (reg != 0)
00542             outfishy();
00543     }
00544     else
00545     {
00546         getmodregrm();
00547         outustr(movtab);
00548         if (!(opc & TOREGBIT))
00549         {
00550             Ev();
00551             outcomma();
00552         }
00553         outustr(segreg[reg]);
00554         if (opc & TOREGBIT)
00555         {
00556             outcomma();
00557             Ev();
00558         }
00559     }
00560 }
00561 
00562 PRIVATE void i_90(opc)
00563 opcode_pt opc;
00564 {
00565     if (opc == 0)
00566         outustr("nop");
00567     else
00568     {
00569         outustr("xchg\t");
00570         outax();
00571         outcomma();
00572         outustr(genreg[hosize + opc]);
00573     }
00574 }
00575 
00576 PRIVATE void i_98(opc)
00577 opcode_pt opc;
00578 {
00579     outustr((str_98 - 8)[opc + hosize]);
00580     if (opc == 2)
00581         outsegpc();
00582 }
00583 
00584 PRIVATE void i_a0(opc)
00585 opcode_pt opc;
00586 {
00587     outustr(str_a0[opc]);
00588     if (opc < 4)
00589     {
00590         mod = MEM0_MOD;         /* fake */
00591         reg = 0;                /* fake ax */
00592         if (hasize == 16)
00593             rm = 5;             /* fake [d16] */
00594         else
00595             rm = 6;             /* fake [d32] */
00596         outad1(opc ^ TOREGBIT);
00597     }
00598     else if (opc & 1)
00599         outwsize();
00600 }
00601 
00602 PRIVATE void i_a8(opc)
00603 opcode_pt opc;
00604 {
00605     outustr(str_a8[opc]);
00606     if (opc < 2)
00607     {
00608         outalorx(opc);
00609         outcomma();
00610         outimmed(opc);
00611     }
00612     else if (opc & 1)
00613         outwsize();
00614 }
00615 
00616 PRIVATE void i_b0(opc)
00617 opcode_pt opc;
00618 {
00619     outustr(movtab);
00620     outustr(genreg[opc]);
00621     outcomma();
00622     Ib();
00623 }
00624 
00625 PRIVATE void i_b8(opc)
00626 opcode_pt opc;
00627 {
00628     outustr(movtab);
00629     outustr(genreg[hosize + opc]);
00630     outcomma();
00631     Iv();
00632 }
00633 
00634 PRIVATE void i_c0(opc)
00635 opcode_pt opc;
00636 {
00637     outustr(str_c0[opc]);
00638     if (opc >= 6)
00639     {
00640         getmodregrm();
00641         outbwptr(opc);
00642         outea(opc);
00643         outcomma();
00644         outimmed(opc & WORDBIT);
00645         if (reg != 0)
00646             /* not completely decoded (like DEBUG) */
00647             outfishy();
00648     }
00649     else if (opc >= 4)
00650         GvMp();
00651     else if (opc == 2)
00652         Iv();
00653     else if (opc < 2)
00654         shift(opc);
00655 }
00656 
00657 PRIVATE void i_c8(opc)
00658 opcode_pt opc;
00659 {
00660     outustr(str_c8[opc]);
00661     if (opc == 0)
00662     {
00663         Iw();
00664         outcomma();
00665         Ib();
00666     }
00667     if (opc == 2)
00668         Iv();
00669     else if (opc == 5)
00670         Ib();
00671     else if (opc == 7 && hosize == 16)
00672         outwsize();
00673 }
00674 
00675 PRIVATE void i_d0(opc)
00676 opcode_pt opc;
00677 {
00678     opcode_pt aabyte;
00679 
00680     if (opc < 4)
00681         shift(opc | 0xD0);
00682     else
00683     {
00684         outustr((str_d0 - 4)[opc]);
00685         if (opc < 6 && (aabyte = get8()) != 0x0A)
00686         {
00687             outtab();
00688             outh8(aabyte);
00689             outfishy();
00690         }
00691     }
00692 }
00693 
00694 PRIVATE void i_d8(opc)
00695 opcode_pt opc;
00696 {
00697     opcode_pt esc;
00698     char *str;
00699 
00700     getmodregrm();
00701     esc = (opc << 3) | reg;
00702     if ((str = (mod == REG_MOD ? str1_d8 : str_d8)[esc]) == NULL)
00703     {
00704 escape:
00705         oututstr("esc");
00706         outh8(esc);
00707         outcomma();
00708         outea(0);
00709         return;
00710     }
00711     if (*str == 0)
00712     {
00713         str = sstr_d8[str[1] + rm];
00714         if (str == NULL)
00715             goto escape;
00716         outustr(str);
00717         return;
00718     }
00719     outustr(str);
00720     outtab(); 
00721     if (mod == REG_MOD)
00722     {
00723         if (opc == 0 && reg != 2 && reg != 3)
00724             outustr("st,");
00725         outf1();
00726         if (opc == 4 || opc == 6)
00727             outustr(",st");
00728         return; 
00729     }
00730     switch(size_d8[esc])
00731     {
00732     case 4:
00733         outustr("d");
00734     case 2:
00735         outwptr();
00736         break;
00737     case 8:
00738         outustr("q");
00739         outwptr();
00740         break;
00741     case 10:
00742         outustr("t");
00743         outbptr();
00744         break;
00745     }
00746     outea(opc);
00747 }
00748 
00749 PRIVATE void i_e0(opc)
00750 opcode_pt opc;
00751 {
00752     outustr(str_e0[opc]);
00753     if (opc < 4)
00754         Jb();
00755     else if (opc < 6)
00756     {
00757         outalorx(opc);
00758         outcomma();
00759         Ib();
00760     }
00761     else
00762     {
00763         Ib();
00764         outcomma();
00765         outalorx(opc);
00766     }
00767 }
00768 
00769 PRIVATE void i_e8(opc)
00770 opcode_pt opc;
00771 {
00772     outustr(str_e8[opc]);
00773     if (opc < 2)
00774         Jv();
00775     else if (opc == 2)
00776         outsegpc();
00777     else if (opc == 3)
00778         Jb();
00779     else
00780     {
00781         if (opc & TOREGBIT)
00782         {
00783             outustr(genreg[10]);
00784             outcomma();
00785             outalorx(opc);
00786         }
00787         else
00788         {
00789             outalorx(opc);
00790             outcomma();
00791             outustr(genreg[10]);
00792         }
00793     }
00794 }
00795 
00796 PRIVATE void i_f0(opc)
00797 opcode_pt opc;
00798 {
00799     if (opc < 6)
00800         outustr(str_f0[opc]);
00801     else
00802     {
00803         getmodregrm();
00804         outustr(sstr_f0[reg]);
00805         outbwptr(opc);
00806         outea(opc);
00807         if (reg == 0)
00808         {
00809             outcomma();
00810             outimmed(opc & WORDBIT);
00811         }
00812     }
00813 }
00814 
00815 PRIVATE void i_f8(opc)
00816 opcode_pt opc;
00817 {
00818     if (opc < 6)
00819         outustr(str_f8[opc]);
00820     else
00821     {
00822         getmodregrm();
00823         if (opc == 6 && reg >= 2)
00824             outustr("fishy\t");
00825         else
00826             outustr(sstr_f8[reg]);
00827         outbwptr(opc);
00828         outea(opc);
00829     }
00830 }
00831 
00832 PRIVATE void outad(opc)
00833 opcode_pt opc;
00834 {
00835     getmodregrm();
00836     outad1(opc);
00837 }
00838 
00839 PRIVATE void outad1(opc)
00840 opcode_pt opc;
00841 {
00842     if (!(opc & TOREGBIT))
00843     {
00844         outea(opc);
00845         outcomma();
00846     }
00847     if (opc & WORDBIT)
00848         Gv1();
00849     else
00850         outustr(genreg[reg]);
00851     if (opc & TOREGBIT)
00852     {
00853         outcomma();
00854         outea(opc);
00855     }
00856 }
00857 
00858 PRIVATE void outalorx(opc)
00859 opcode_pt opc;
00860 {
00861     if (opc & WORDBIT)
00862         outax();
00863     else
00864         outustr(genreg[0]);
00865 }
00866 
00867 PRIVATE void outax()
00868 {
00869     outustr(genreg[hosize]);
00870 }
00871 
00872 PRIVATE void outbptr()
00873 {
00874     outustr("byte ptr ");
00875 }
00876 
00877 PRIVATE void outbwptr(opc)
00878 opcode_pt opc;
00879 {
00880     if (mod != REG_MOD)
00881     {
00882         if (opc & WORDBIT)
00883             outwptr();
00884         else
00885             outbptr();
00886     }
00887 }
00888 
00889 PRIVATE void outea(wordflags)
00890 opcode_pt wordflags;
00891 {
00892     reg_pt base;
00893     reg_pt index;
00894     opcode_pt ss;
00895     opcode_pt ssindexbase;
00896 
00897     if (mod == REG_MOD)
00898         outustr(genreg[hosize * (wordflags & WORDBIT) + rm]);
00899     else
00900     {
00901         outbyte(LINDIRECT);
00902         if (hasize == 16)
00903         {
00904             if (rm == 4)
00905             {
00906                 base = (ssindexbase = get8()) & BASE_MASK;
00907                 if (mod == MEM0_MOD && base == 5)
00908                     outgetaddr();
00909                 else
00910                     outustr((genreg + 16)[base]);
00911                 ss = (ssindexbase & SS_MASK) >> SS_SHIFT;
00912                 if ((index = (ssindexbase & INDEX_MASK) >> INDEX_SHIFT) != 4)
00913                 {
00914                     outbyte('+');
00915                     outustr((genreg + 16)[index]);
00916                     outstr("\0\0\0*2\0*4\0*8\0" + (3 * ss));
00917                 }
00918             }
00919             else if (mod == MEM0_MOD && rm == 5)
00920                 outgetaddr();
00921             else
00922                 outustr((genreg + 16)[rm]);
00923         }
00924         else if (mod == MEM0_MOD && rm == 6)
00925             outgetaddr();
00926         else
00927             outustr(indreg[rm]);
00928         if (mod == MEM1_MOD)
00929             /* fake sign extension to get +- */
00930             outimmed(SIGNBIT | WORDBIT);
00931         else if (mod == MEM2_MOD)
00932         {
00933             outbyte('+');
00934 #if (_WORD_SIZE == 4)
00935             out32offset();
00936 #else
00937             outgetaddr();
00938 #endif
00939         }
00940         outbyte(RINDIRECT);
00941         if (hasize == 16 && rm == 4 && index == 4 && ss != 0)
00942             outfishy();
00943     }
00944 }
00945 
00946 PRIVATE void outf1()
00947 {
00948     outustr("st(");
00949     outbyte((int) (rm + '0'));
00950     outbyte(')');
00951 }
00952 
00953 #if (_WORD_SIZE == 4)
00954 
00955 PRIVATE void out32offset()
00956 {
00957     off_t off;
00958 
00959     if (hasize == 16)
00960         off = get32();
00961     else
00962         outfishy();
00963 
00964     outh32(off);
00965 }
00966 #endif
00967 
00968 PRIVATE void outfishy()
00969 {
00970     outustr("\t???");
00971 }
00972 
00973 PRIVATE void outgetaddr()
00974 {
00975     off_t off;
00976 
00977     if (hasize == 16)
00978         off = get32();
00979     else
00980         off = get16();
00981 
00982     if ( finds_data(off,data_seg) )
00983         *offptr++ = off;
00984     else if (hasize == 16)
00985         outh32(off);
00986     else
00987         outh16((u16_t) off);
00988 }
00989 
00990 PRIVATE void outimmed(signwordflag)
00991 opcode_pt signwordflag;
00992 {
00993     su8_pt byte;
00994 
00995     if (signwordflag & WORDBIT)
00996     {
00997         if (signwordflag & SIGNBIT)
00998         {
00999             if ((byte = get8s()) < 0)
01000             {
01001                 outbyte('-');
01002                 byte = -byte;
01003             }
01004             else
01005                 outbyte('+');
01006             outh8((u8_t) byte);
01007         }
01008         else
01009             Iv();
01010     }
01011     else
01012         Ib();
01013 }
01014 
01015 PRIVATE void outpc(pc)
01016 off_t pc;
01017 {
01018     if (hosize == 8)
01019         pc = (u16_t) pc;
01020 
01021     if ( finds_pc(pc) )
01022         *offptr++ = pc;
01023     else if (hosize == 16)
01024         outh32(pc);
01025     else
01026         outh16((u16_t) pc);
01027 }
01028 
01029 PRIVATE void outsegpc()
01030 {
01031     off_t oldbase;
01032     off_t pc;
01033 
01034     if (hosize == 16)
01035         pc = get32();
01036     else
01037         pc = get16();
01038     oldbase = uptr.base;
01039     outh16((u16_t) (uptr.base = get16()));      /* fake seg for lookup of pc */
01040                         /* TODO - convert to offset in protected mode */
01041     outbyte(':');
01042     outpc(pc);
01043     uptr.base = oldbase;
01044 }
01045 
01046 PRIVATE void oututstr(s)
01047 char *s;
01048 {
01049     outustr(s);
01050     outtab();
01051 }
01052 
01053 PRIVATE void outword()
01054 {
01055     outustr("dword " + ((16 - hosize) >> 3));
01056 }
01057 
01058 PRIVATE void outwptr()
01059 {
01060     outword();
01061     outustr("ptr ");
01062 }
01063 
01064 PRIVATE void outwsize()
01065 {
01066     if (hosize == 16)
01067         outustr("d");
01068     else
01069         outustr("w");
01070 }
01071 
01072 PRIVATE void pagef()
01073 {
01074     opcode_pt opc;
01075     int regbad;
01076 
01077     if ((opc = get8()) <= 1 || opc == 0xBA)
01078     {
01079         if (opc == 0xBA)
01080             opc = 16;
01081         else
01082             opc *= 8;
01083         getmodregrm();
01084         outustr(ssstr_0f[opc += reg]);
01085         if (opc < 6 || opc == 12 || opc == 14)
01086             Ew();
01087         else if (opc >= 8 && opc < 13)
01088             Ms();
01089         else if (opc >= 20)
01090         {
01091             outbwptr(WORDBIT);
01092             EvIb();
01093         }
01094     }
01095     else if (opc < 4)
01096     {
01097         oututstr("lar\0lsl" + 4 * (opc - 2));
01098         GvEw();
01099     }
01100     else if (opc == 5)
01101     {
01102         outustr("loadall");
01103         outfishy();
01104     }
01105     else if (opc == 6)
01106         outustr("clts");
01107     else if (opc < 0x20)
01108         outstr(fishy);
01109     else if (opc < 0x27 && opc != 0x25)
01110     {
01111         outustr(movtab);
01112         getmodregrm();
01113         hosize = 16;
01114         if (!(opc & TOREGBIT))
01115         {
01116             Ev();               /* Rd() since hosize is 16 */
01117             outcomma();
01118         }
01119         regbad = FALSE;
01120         if (opc & 1)
01121         {
01122             outustr("dr");
01123             if (reg == 4 || reg == 5)
01124                 regbad = TRUE;
01125         }
01126         else if (opc < 0x24)
01127         {
01128             outustr("cr");
01129             if (reg >= 4 || reg == 1)
01130                 regbad = TRUE;
01131         }
01132         else
01133         {
01134             outustr("tr");
01135             if (reg < 6)
01136                 regbad = TRUE;
01137         }
01138         outbyte((int) (reg + '0'));
01139         if (opc & TOREGBIT)
01140         {
01141             outcomma();
01142             Ev();
01143         }
01144         if (regbad || mod != REG_MOD)
01145             outfishy();
01146     }
01147     else if (opc < 0x80)
01148         outstr(fishy);
01149     else if (opc < 0x90)
01150     {
01151         outustr("j");
01152         oututstr((str_flags - 0x80)[opc]);
01153         Jv();
01154     }
01155     else if (opc < 0xA0)
01156     {
01157         outustr("set");
01158         oututstr((str_flags - 0x90)[opc]);
01159         getmodregrm();
01160         outbwptr(0);
01161         Eb();
01162     }
01163     else if (opc < 0xC0)
01164     {
01165         outustr((sstr_0f - 0xA0)[opc]);
01166         switch (opc)
01167         {
01168         case 0xA3:
01169         case 0xAB:
01170         case 0xB3:
01171         case 0xBB:
01172             EvGv();
01173             break;
01174         case 0xA4:
01175         case 0xAC:
01176             EvGv();
01177             outcomma();
01178             Ib();
01179             break;
01180         case 0xA5:
01181         case 0xAD:
01182             EvGv();
01183             outcomma();
01184             CL();
01185             break;
01186         case 0xAF:
01187         case 0xBC:
01188         case 0xBD:
01189             GvEv();
01190             break;
01191         case 0xB2:
01192         case 0xB4:
01193         case 0xB5:
01194             GvMp();
01195             break;
01196         case 0xB6:
01197         case 0xBE:
01198             Gv();
01199             outcomma();
01200             outbwptr(opc);
01201             Eb();
01202             break;
01203         case 0xB7:
01204         case 0xBF:
01205             Gv();
01206             outcomma();
01207             hosize = 8;         /* done in Ew(), but too late */
01208             outbwptr(opc);
01209             Ew();
01210             break;
01211         }
01212     }
01213     else
01214         outstr(fishy);
01215 }
01216 
01217 PRIVATE int puti()
01218 {
01219     static int hadprefix;
01220     opcode_pt opcode;
01221 
01222 more:
01223     offptr = offtable;
01224     opcode = get8();
01225     if (!hadprefix)
01226     {
01227         data_seg = DSEG;
01228         hdefsize = 8;
01229         if (bits32)
01230             hdefsize = 16;
01231         hosize =
01232             hasize = hdefsize;
01233     }
01234     (*optable[opcode >> 3])(opcode < 0x80 ? opcode : opcode & 7);
01235     if (offptr > offtable)
01236     {
01237         if (stringtab() >= 31)
01238         {
01239             outspace();
01240             outspace();
01241         }
01242         else
01243             while (stringtab() < 32)
01244                 outtab();
01245         outbyte(';');
01246         for (off1ptr = offtable; off1ptr < offptr; ++off1ptr)
01247         {
01248             outspace();
01249             if (*off1ptr < 0x10000)
01250                 outh16((u16_t) *off1ptr);
01251             else
01252                 outh32(*off1ptr);
01253         }
01254         offptr = offtable;
01255     }
01256     if ((opcode & 0xE7) == 0x26 ||
01257         opcode >= 0x64 && opcode < 0x68 ||
01258         opcode == 0xF0 || opcode == 0xF2 || opcode == 0xF3)
01259         /* not finished instruction for 0x26, 0x2E, 0x36, 0x3E seg overrides
01260          * and 0x64, 0x65 386 seg overrides
01261          * and 0x66, 0x67 386 size prefixes
01262          * and 0xF0 lock, 0xF2 repne, 0xF3 rep
01263          */
01264     {
01265         hadprefix = TRUE;
01266         goto more;              /* TODO - print prefixes better */
01267         return FALSE;
01268     }
01269     hadprefix = FALSE;
01270     return TRUE;
01271 }
01272 
01273 PRIVATE void shift(opc)
01274 opcode_pt opc;
01275 {
01276     getmodregrm();
01277     oututstr(sstr_d0[reg]);
01278     outbwptr(opc);
01279     outea(opc);
01280     outcomma();
01281     if (opc < 0xD0)
01282         Ib();
01283     else if (opc & 2)
01284         CL();
01285     else
01286         outbyte('1');
01287 }
01288 
01289 PRIVATE void checkmemory()
01290 {
01291     if (mod == REG_MOD)
01292         outfishy();
01293 }
01294 
01295 PRIVATE void CL()
01296 {
01297     outustr(genreg[1]);
01298 }
01299 
01300 PRIVATE void Eb()
01301 {
01302     outea(0);
01303 }
01304 
01305 PRIVATE void Ev()
01306 {
01307     outea(WORDBIT);
01308 }
01309 
01310 PRIVATE void EvGv()
01311 {
01312     getmodregrm();
01313     Ev();
01314     outcomma();
01315     Gv1();
01316 }
01317 
01318 PRIVATE void EvIb()
01319 {
01320     Ev();
01321     outcomma();
01322     Ib();
01323 }
01324 
01325 PRIVATE void Ew()
01326 {
01327     hosize = 8;
01328     Ev();
01329 }
01330 
01331 PRIVATE void EwRw()
01332 {
01333     hosize = 8;
01334     EvGv();
01335 }
01336 
01337 PRIVATE void Gv()
01338 {
01339     getmodregrm();
01340     Gv1();
01341 }
01342 
01343 PRIVATE void Gv1()
01344 {
01345     outustr(genreg[hosize + reg]);
01346 }
01347 
01348 PRIVATE void GvEv()
01349 {
01350     Gv();
01351     outcomma();
01352     Ev();
01353 }
01354 
01355 PRIVATE void GvEw()
01356 {
01357     Gv();
01358     outcomma();
01359     Ew();
01360 }
01361 
01362 PRIVATE void GvM()
01363 {
01364     GvEv();
01365     checkmemory();
01366 }
01367 
01368 PRIVATE void GvMa()
01369 {
01370     GvM();
01371 }
01372 
01373 PRIVATE void GvMp()
01374 {
01375     GvM();
01376 }
01377 
01378 PRIVATE void Ib()
01379 {
01380     outh8(get8());
01381 }
01382 
01383 PRIVATE void Iw()
01384 {
01385     outh16(get16());
01386 }
01387 
01388 PRIVATE void Iv()
01389 {
01390     if (hosize == 16)
01391         outh32(get32());
01392     else
01393         Iw();
01394 }
01395 
01396 PRIVATE void Jb()
01397 {
01398     off_t pcjump;
01399 
01400     pcjump = get8s();
01401     outpc(pcjump + uptr.off);
01402 }
01403 
01404 PRIVATE void Jv()
01405 {
01406     off_t pcjump;
01407 
01408     if (hosize == 16)
01409         pcjump = get32();
01410     else
01411         pcjump = (su16_t) get16();
01412     outpc(pcjump + uptr.off);
01413 }
01414 
01415 PRIVATE void Ms()
01416 {
01417     Ev();
01418     checkmemory();
01419 }
01420 
01421 /********************* DASM ******************************/
01422 
01423 PUBLIC long dasm( addr, count, symflg )
01424 long addr;
01425 int count;
01426 int symflg;
01427 {
01428 #if (_WORD_SIZE == 4)
01429         bits32 = TRUE;          /* Set mode */
01430 #else
01431         bits32 = FALSE;
01432 #endif
01433         uptr.off = addr;
01434         uptr.base = 0;          /* not known */
01435         while ( count-- != 0 && show1instruction() )
01436                 ;
01437 }
01438 
01439 
01440 PRIVATE int show1instruction()
01441 {
01442     register int column;
01443     int idone;
01444     static char line[81];
01445     int maxcol;
01446     struct address_s newuptr;
01447     struct address_s olduptr;
01448 
01449     outbyte('\r');
01450     do
01451     {
01452         if ( text_symbol(uptr.off) ) {
01453             outbyte(':');
01454             outbyte('\n');
01455         }
01456         olduptr = uptr;
01457         openstring(line);
01458         idone = puti();
01459         line[stringpos()] = 0;
01460         closestring();
01461         newuptr = uptr;
01462         uptr = olduptr;
01463         column = outssegaddr(&uptr);
01464         while (uptr.off != newuptr.off)
01465         {
01466             outh8(get8());
01467             column += 2;
01468         }
01469         maxcol = bits32 ? 24 : 16;
01470         while (column < maxcol)
01471         {
01472             outtab();
01473             column += 8;
01474         }
01475         outtab();
01476         outstr(line);
01477         outbyte('\n');
01478     }
01479     while (!idone);             /* eat all prefixes */
01480     return TRUE;
01481 }
01482 
01483 
01484 PRIVATE u8_t get8()
01485 {
01486 /* get 8 bits current instruction pointer and advance pointer */
01487 
01488     u8_t temp;
01489 
01490     temp = peek_byte(uptr.off + uptr.base);
01491     ++uptr.off;
01492     return temp;
01493 }
01494 
01495 PRIVATE u16_t get16()
01496 {
01497 /* get 16 bits from current instruction pointer and advance pointer */
01498 
01499     u16_t temp;
01500 
01501     temp = peek_word(uptr.off + uptr.base);
01502     uptr.off += 2;
01503     return temp;
01504 }
01505 
01506 PRIVATE u32_t get32()
01507 {
01508 /* get 32 bits from current instruction pointer and advance pointer */
01509 
01510     u32_t temp;
01511 
01512     temp = peek_dword(uptr.off + uptr.base);
01513     uptr.off += 4;
01514     return temp;
01515 }
01516 
01517 
01518 PRIVATE int outsegaddr(addr)
01519 struct address_s *addr;
01520 {
01521 /* print segmented address */
01522 
01523     int bytes_printed;
01524 
01525     bytes_printed = 2;
01526         bytes_printed = outsegreg(addr->base);
01527     if (bytes_printed > 4)
01528         outbyte('+');
01529     else
01530         outbyte(':');
01531     ++bytes_printed;
01532     if (addr->off >= 0x10000)
01533     {
01534         outh32(addr->off);
01535         return bytes_printed + 8;
01536     }
01537     outh16((u16_t) addr->off);
01538     return bytes_printed + 4;
01539 }
01540 
01541 PRIVATE int outssegaddr(addr)
01542 struct address_s *addr;
01543 {
01544 /* print 32 bit segmented address and 2 spaces */
01545 
01546     int bytes_printed;
01547 
01548     bytes_printed = outsegaddr(addr);
01549     outspace();
01550     outspace();
01551     return bytes_printed + 2;
01552 }
01553 
01554 PRIVATE u8_t peek_byte(addr)
01555 off_t addr;
01556 {
01557     return (u8_t) peek_dword(addr) & 0xFF; /* 8 bits only */
01558 }
01559 
01560 PRIVATE u16_t peek_word(addr)
01561 off_t addr;
01562 {
01563     return (u16_t) peek_dword(addr);
01564 }

Generated on Fri Apr 14 22:57:00 2006 for minix by  doxygen 1.4.6