home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / debug / edebug / unassmbl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-26  |  28.7 KB  |  1,120 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. /*
  4. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  5. **
  6. ** This file is distributed under the terms listed in the document
  7. ** "copying.dj", available from DJ Delorie at the address above.
  8. ** A copy of "copying.dj" should accompany this file; if not, a copy
  9. ** should be available from where this file was obtained.  This file
  10. ** may not be distributed without a verbatim copy of "copying.dj".
  11. **
  12. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  13. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. */
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18.  
  19. #include "ed.h"
  20. #include "unassmbl.h"
  21. #include <debug/syms.h>
  22.  
  23. #define SOURCE_LIST
  24.  
  25. int seg_size=32;
  26.  
  27. static word8 buf[20];
  28. static word32 vaddr;
  29. static int bufp, bufe;
  30. static char ubuf[4000], *ubufp;
  31. static col;
  32.  
  33. static void ua_str(const char *s);
  34.  
  35. /* Percent tokens in strings:
  36.    First char after '%':
  37.         A - direct address
  38.         C - reg of r/m picks control register
  39.         D - reg of r/m picks debug register
  40.         E - r/m picks operand
  41.         F - flags register
  42.         G - reg of r/m picks general register
  43.         I - immediate data (takes extended size, data size)
  44.         J - relative IP offset
  45.         M - r/m picks memory
  46.         O - no r/m, offset only
  47.         R - mod of r/m picks register only
  48.         S - reg of r/m picks segment register
  49.         T - reg of r/m picks test register
  50.         X - DS:ESI
  51.         Y - ES:EDI
  52.         2 - prefix of two-byte opcode
  53.         e - put in 'e' if use32 (second char is part of reg name)
  54.             put in 'w' for use16 or 'd' for use32 (second char is 'w')
  55.         f - floating point (second char is esc value)
  56.         g - do r/m group 'n'
  57.         p - prefix
  58.         s - size override (second char is a,o)
  59.         + - make default signed
  60.    Second char after '%':
  61.         a - two words in memory (BOUND)
  62.         b - byte
  63.         c - byte or word
  64.         d - dword
  65.         p - 32 or 48 bit pointer
  66.         s - six byte pseudo-descriptor
  67.         v - word or dword
  68.         w - word
  69.         F - use floating regs in mod/rm
  70.         + - always sign
  71.         - - sign if negative
  72.         1-8 - group number, esc value, etc
  73. */
  74.  
  75. const char *opmap1[] = {
  76. /* 0 */
  77.   "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev",
  78.   "add al,%I-bb", "add %eax,%I-vv", "push es", "pop es",
  79.   "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev",
  80.   "or al,%Ibb", "or %eax,%Ivv", "push cs", "%2 ",
  81. /* 1 */
  82.   "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev",
  83.   "adc al,%I-bb", "adc %eax,%I-vv", "push ss", "pop ss",
  84.   "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev",
  85.   "sbb al,%I-bb", "sbb %eax,%I-vv", "push ds", "pop ds",
  86. /* 2 */
  87.   "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev",
  88.   "and al,%Ibb", "and %eax,%Ivv", "%pe", "daa",
  89.   "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev",
  90.   "sub al,%I-bb", "sub %eax,%I-vv", "%pc", "das",
  91. /* 3 */
  92.   "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev",
  93.   "xor al,%Ibb", "xor %eax,%Ivv", "%ps", "aaa",
  94.   "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev",
  95.   "cmp al,%I-bb", "cmp %eax,%I-vv", "%pd", "aas",
  96. /* 4 */
  97.   "inc %eax", "inc %ecx", "inc %edx", "inc %ebx",
  98.   "inc %esp", "inc %ebp", "inc %esi", "inc %edi",
  99.   "dec %eax", "dec %ecx", "dec %edx", "dec %ebx",
  100.   "dec %esp", "dec %ebp", "dec %esi", "dec %edi",
  101. /* 5 */
  102.   "push %eax", "push %ecx", "push %edx", "push %ebx",
  103.   "push %esp", "push %ebp", "push %esi", "push %edi",
  104.   "pop %eax", "pop %ecx", "pop %edx", "pop %ebx",
  105.   "pop %esp", "pop %ebp", "pop %esi", "pop %edi",
  106. /* 6 */
  107.   "pusha", "popa", "bound %Gv,%Ma", "arpl %Ew,%Rw",
  108.   "%pf", "%pg", "%so", "%sa",
  109.   "push %I-vv", "imul %Gv=%Ev*%I-vv", "push %I-vb", "imul %Gv=%Ev*%I-vb",
  110.   "insb %Yb,dx", "ins%ew %Yv,dx", "outsb dx,%Xb", "outs%ew dx,%Xv",
  111. /* 7 */
  112.   "jo %Jb", "jno %Jb", "jc %Jb", "jnc %Jb",
  113.   "jz %Jb", "jnz %Jb", "jbe %Jb", "jnbe %Jb",
  114.   "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb",
  115.   "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb",
  116. /* 8 */
  117.   "%g1 %Eb,%Ibb", "%g1 %Ev,%Ivv", 0, "%g1 %Ev,%Ivb",
  118.   "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv",
  119.   "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev",
  120.   "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev",
  121. /* 9 */
  122.   "nop", "xchg %eax,%ecx", "xchg %eax,%edx", "xchg %eax,%ebx",
  123.   "xchg %eax,%esp", "xchg %eax,%ebp", "xchg %eax,%esi", "xchg %eax,%edi",
  124.   "cbw", "cwd", "call %Ap", "fwait",
  125.   "push %eflags", "pop %eflags", "sahf", "lahf",
  126. /* a */
  127.   "mov al,%Ob", "mov %eax,%Ov", "mov %Ob,al", "mov %Ov,%eax",
  128.   "movsb %Xb,%Yb", "movs%ew %Xv,%Yv", "cmpsb %Xb,%Yb", "cmps%ew %Xv,%Yv",
  129.   "test al,%Ibb", "test %eax,%Ivv", "stosb %Yb,al", "stos%ew %Yv,%eax",
  130.   "lodsb al,%Xb", "lods%ew %eax,%Xv", "scasb al,%Xb", "scas%ew %eax,%Xv",
  131. /* b */
  132.   "mov al,%Ibb", "mov cl,%Ibb", "mov dl,%Ibb", "mov bl,%Ibb",
  133.   "mov ah,%Ibb", "mov ch,%Ibb", "mov dh,%Ibb", "mov bh,%Ibb",
  134.   "mov %eax,%I-vv", "mov %ecx,%I-vv", "mov %edx,%I-vv", "mov %ebx,%I-vv",
  135.   "mov %esp,%Ivv", "mov %ebp,%Ivv", "mov %esi,%I-vv", "mov %edi,%I-vv",
  136. /* c */
  137.   "%g2 %Eb,%Ibb", "%g2 %Ev,%Ibb", "ret %Iw", "ret",
  138.   "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ibb", "mov %Ev,%I-vv",
  139.   "enter %Iww,%Ibb", "leave", "retf %Iww", "retf",
  140.   "int 3", "int %Ibb", "into", "iret",
  141. /* d */
  142.   "%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl",
  143.   "aam %Ibb", "aad %Ibb", 0, "xlat",
  144.   "%f0", "%f1", "%f2", "%f3",
  145.   "%f4", "%f5", "%f6", "%f7",
  146. /* e */
  147.   "loopne %Jb", "loope %Jb", "loop %Jb", "jcxz %Jb",
  148.   "in al,%Ibb", "in %eax,%Ibb", "out %Ibb,al", "out %Ibb,%eax",
  149.   "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Jb",
  150.   "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax",
  151. /* f */
  152.   "lock %p ", 0, "repne %p ", "rep(e) %p ",
  153.   "hlt", "cmc", "%g3", "%g0",
  154.   "clc", "stc", "cli", "sti",
  155.   "cld", "std", "%g4", "%g5"
  156.   };
  157.  
  158. const char *second[] = {
  159. /* 0 */
  160.   "%g6", "%g7", "lar %Gv,%Ew", "lsl %Gv,%Ew", 0, 0, "clts", 0,
  161.   0, 0, 0, 0, 0, 0, 0, 0,
  162. /* 1 */
  163.   0, 0, 0, 0, 0, 0, 0, 0,
  164.   0, 0, 0, 0, 0, 0, 0, 0,
  165. /* 2 */
  166.   "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd",
  167.   "mov %Rd,%Td", 0, "mov %Td,%Rd", 0,
  168.   0, 0, 0, 0, 0, 0, 0, 0,
  169. /* 3 */
  170.   0, 0, 0, 0, 0, 0, 0, 0,
  171.   0, 0, 0, 0, 0, 0, 0, 0,
  172.   0, 0, 0, 0, 0, 0, 0, 0,
  173.   0, 0, 0, 0, 0, 0, 0, 0,
  174.   0, 0, 0, 0, 0, 0, 0, 0,
  175.   0, 0, 0, 0, 0, 0, 0, 0,
  176.   0, 0, 0, 0, 0, 0, 0, 0,
  177.   0, 0, 0, 0, 0, 0, 0, 0,
  178.   0, 0, 0, 0, 0, 0, 0, 0,
  179.   0, 0, 0, 0, 0, 0, 0, 0,
  180. /* 8 */
  181.   "jo %Jv", "jno %Jv", "jc %Jv", "jnc %Jv",
  182.   "jz %Jv", "jnz %Jv", "jbe %Jv", "jnbe %Jv",
  183.   "js %Jv", "jns %Jv", "jpe %Jv", "jpo %Jv",
  184.   "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv",
  185. /* 9 */
  186.   "seto %Eb", "setno %Eb", "setc %Eb", "setnc %Eb",
  187.   "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb",
  188.   "sets %Eb", "setns %Eb", "setp %Eb", "setnp %Eb",
  189.   "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb",
  190. /* a */
  191.   "push fs", "pop fs", 0, "bt %Ev,%Gv",
  192.   "shld %Ev,%Gv,%Ibb", "shld %Ev,%Gv,cl", 0, 0,
  193.   "push gs", "pop gs", 0, "bts %Ev,%Gv",
  194.   "shrd %Ev,%Gv,%Ibb", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev",
  195. /* b */
  196.   0, 0, "lss %Mp", "btr %Ev,%Gv",
  197.   "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew",
  198.   0, 0, "%g8 %Ev,%Ibb", "btc %Ev,%Gv",
  199.   "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew",
  200. /* c */
  201.   0, 0, 0, 0, 0, 0, 0, 0,
  202.   0, 0, 0, 0, 0, 0, 0, 0,
  203.   0, 0, 0, 0, 0, 0, 0, 0,
  204.   0, 0, 0, 0, 0, 0, 0, 0,
  205.   0, 0, 0, 0, 0, 0, 0, 0,
  206.   0, 0, 0, 0, 0, 0, 0, 0,
  207.   0, 0, 0, 0, 0, 0, 0, 0,
  208.   0, 0, 0, 0, 0, 0, 0, 0,
  209.   };
  210.  
  211. const char *groups[][8] = {     /* group 0 is group 3 for %Ev set */
  212.   { "test %Ev,%Ivv", "test %Ev,%Ivv,", "not %Ev", "neg %Ev",
  213.     "mul %eax,%Ev", "imul %eax,%Ev", "div %eax,%Ev", "idiv %eax,%Ev" },
  214.   { "add%+-", "or", "adc%+-", "sbb%+-", "and", "sub%+-", "xor", "cmp%+-" },
  215.   { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" },
  216.   { "test %Eb,%Ibb", "test %Eb,%Ibb,", "not %Eb", "neg %Eb",
  217.     "mul al,%Eb", "imul al,%Eb", "div al,%Eb", "idiv al,%Eb" },
  218.   { "inc %Eb", "dec %Eb", 0, 0, 0, 0, 0, 0 },
  219.   { "inc %Ev", "dec %Ev", "call %Ev", "call %Ep",
  220.     "jmp %Ev", "jmp %Ep", "push %Ev", 0 },
  221.   { "sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew",
  222.     "verr %Ew", "verw %Ew", 0, 0 },
  223.   { "sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms",
  224.     "smsw %Ew", 0, "lmsw %Ew", 0 },
  225.   { 0, 0, 0, 0, "bt", "bts", "btr", "btc" }
  226.   };
  227.  
  228. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  229. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  230. const char *f0[] = {0, 0, 0, 0, 0, 0, 0, 0};
  231. const char *fop_9[]  = { "*fxch st,%GF" };
  232. const char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 };
  233. const char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 };
  234. const char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi",
  235.                          "fldlg2", "fldln2", "fldz", 0 };
  236. const char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
  237.                          "fxtract", "fprem1", "fdecstp", "fincstp" };
  238. const char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos",
  239.                          "frndint", "fscale", "fsin", "fcos" };
  240. const char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 };
  241. const char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 };
  242. const char *fop_32[] = { "*fadd %GF,st" };
  243. const char *fop_33[] = { "*fmul %GF,st" };
  244. const char *fop_36[] = { "*fsubr %GF,st" };
  245. const char *fop_37[] = { "*fsub %GF,st" };
  246. const char *fop_38[] = { "*fdivr %GF,st" };
  247. const char *fop_39[] = { "*fdiv %GF,st" };
  248. const char *fop_40[] = { "*ffree %GF" };
  249. const char *fop_42[] = { "*fst %GF" };
  250. const char *fop_43[] = { "*fstp %GF" };
  251. const char *fop_44[] = { "*fucom %GF" };
  252. const char *fop_45[] = { "*fucomp %GF" };
  253. const char *fop_48[] = { "*faddp %GF,st" };
  254. const char *fop_49[] = { "*fmulp %GF,st" };
  255. const char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 };
  256. const char *fop_52[] = { "*fsubrp %GF,st" };
  257. const char *fop_53[] = { "*fsubp %GF,st" };
  258. const char *fop_54[] = { "*fdivrp %GF,st" };
  259. const char *fop_55[] = { "*fdivp %GF,st" };
  260. const char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
  261.  
  262. const char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  263.   0, 0, 0, 0, 0, 0, 0, 0,
  264.   0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  265.   f0, f0, f0, f0, f0, fop_21, f0, f0,
  266.   f0, f0, f0, f0, fop_28, f0, f0, f0,
  267.   fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  268.   fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  269.   fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  270.   f0, f0, f0, f0, fop_60, f0, f0, f0,
  271.   };
  272.  
  273. const char *floatops[] = { /* assumed " %EF" at end of each.  mod != 3 only */
  274. /*00*/ "fadd", "fmul", "fcom", "fcomp",
  275.        "fsub", "fsubr", "fdiv", "fdivr",
  276. /*08*/ "fld", 0, "fst", "fstp",
  277.        "fldenv", "fldcw", "fstenv", "fstcw",
  278. /*16*/ "fiadd", "fimul", "ficomw", "ficompw",
  279.        "fisub", "fisubr", "fidiv", "fidivr",
  280. /*24*/ "fild", 0, "fist", "fistp",
  281.        "frstor", "fldt", 0, "fstpt",
  282. /*32*/ "faddq", "fmulq", "fcomq", "fcompq",
  283.        "fsubq", "fsubrq", "fdivq", "fdivrq",
  284. /*40*/ "fldq", 0, "fstq", "fstpq",
  285.        0, 0, "fsave", "fstsww",
  286. /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw",
  287.        "fisubw", "fisubrw", "fidivw", "fidivr",
  288. /*56*/ "fildw", 0, "fistw", "fistpw",
  289.        "fbldt", "fildq", "fbstpt", "fistpq"
  290.   };
  291.  
  292. static word8 getbyte(void)
  293. {
  294.   int s;
  295.   if (bufp >= bufe)
  296.   {
  297.     s = 20;
  298.     if ((vaddr & 0xfff) + s > 0x1000)
  299.       s = 0x1000 - (vaddr & 0xfff);
  300.     read_child(vaddr, buf, s);
  301.     bufe = s;
  302.     bufp = 0;
  303.   }
  304.   vaddr++;
  305.   printf("%02x", buf[bufp]);
  306.   col+=2;
  307.   return buf[bufp++];
  308. }
  309.  
  310. static int default_pick_sign;
  311.  
  312. static prefix;
  313. static modrmv;
  314. static sibv;
  315. static opsize;
  316. static addrsize;
  317.  
  318. static int modrm(void)
  319. {
  320.   if (modrmv == -1)
  321.     modrmv = getbyte();
  322.   return modrmv;
  323. }
  324.  
  325. static int sib(void)
  326. {
  327.   if (sibv == -1)
  328.     sibv = getbyte();
  329.   return sibv;
  330. }
  331.  
  332. #define mod(a)  (((a)>>6)&7)
  333. #define reg(a)  (((a)>>3)&7)
  334. #define rm(a)   ((a)&7)
  335. #define ss(a)   (((a)>>6)&7)
  336. #define indx(a) (((a)>>3)&7)
  337. #define base(a) ((a)&7)
  338.  
  339. /*------------------------------------------------------------------------*/
  340. static void uprintf(const char *s, ...)
  341. {
  342.   const char **a = &s;
  343.   vsprintf(ubufp, s, a+1);
  344.   while (*ubufp) ubufp++;
  345. }
  346.  
  347. static void uputchar(char c)
  348. {
  349.   if (c == '\t')
  350.   {
  351.     do {
  352.       *ubufp++ = ' ';
  353.     } while ((ubufp-ubuf) % 8);
  354.   }
  355.   else
  356.     *ubufp++ = c;
  357.   *ubufp = 0;
  358. }
  359.  
  360. /*------------------------------------------------------------------------*/
  361. static int bytes(char c)
  362. {
  363.   switch (c)
  364.   {
  365.     case 'b':
  366.       return 1;
  367.     case 'w':
  368.       return 2;
  369.     case 'd':
  370.       return 4;
  371.     case 'v':
  372.       if (opsize == 32)
  373.         return 4;
  374.       else
  375.         return 2;
  376.   }
  377.   return 0;
  378. }
  379.  
  380. /*------------------------------------------------------------------------*/
  381. static void ohex(char c, int extend, int optional, int defsize, int sign)
  382. {
  383.   static const char *formats[4] = { "%#x", "%d", "%+d", "%+d" };
  384.   const char *fmt;
  385.   int n=0, s=0, i;
  386.   int32 delta;
  387.   unsigned char buf1[6];
  388.   char *name;
  389.   fmt = formats[sign];
  390.  
  391.   switch (c)
  392.   {
  393.     case 'a':
  394.       break;
  395.     case 'b':
  396.       n = 1;
  397.       break;
  398.     case 'w':
  399.       n = 2;
  400.       break;
  401.     case 'd':
  402.       n = 4;
  403.       break;
  404.     case 's':
  405.       n = 6;
  406.       break;
  407.     case 'c':
  408.     case 'v':
  409.       if (defsize == 32)
  410.         n = 4;
  411.       else
  412.         n = 2;
  413.       break;
  414.     case 'p':
  415.       if (defsize == 32)
  416.         n = 6;
  417.       else
  418.         n = 4;
  419.       s = 1;
  420.       break;
  421.     case 'x':
  422.       return;
  423.   }
  424.   for (i=0; i<n; i++)
  425.     buf1[i] = getbyte();
  426.   for (; i<extend; i++)
  427.     buf1[i] = (buf[i-1] & 0x80) ? 0xff : 0;
  428.   if (s)
  429.   {
  430.     uprintf("0x%02x%02x:", buf1[n-1], buf1[n-2]);
  431.     n -= 2;
  432.   }
  433.   switch (n)
  434.   {
  435.     case 1:
  436.       delta = *(signed char *)buf1;
  437.       break;
  438.    case 2:
  439.       delta = *(signed short *)buf1;
  440.       break;
  441.     case 4:
  442.       delta = *(signed long *)buf1;
  443.       break;
  444.   }
  445.   if (extend > n)
  446.   {
  447.     if (delta || !optional)
  448.     {
  449.       uprintf(fmt, delta);
  450.     }
  451.     return;
  452.   }
  453.   if ((n == 4) && sign < 2)
  454.   {
  455.     name = syms_val2name(delta, &delta);
  456.     if (name)
  457.     {
  458.       uprintf("%s", name);
  459.       if (delta)
  460.         uprintf("+%lu", delta);
  461.       return;
  462.     }
  463.   }
  464.   switch (n)
  465.   {
  466.     case 1:
  467.       uprintf(fmt, (unsigned char)delta);
  468.       break;
  469.     case 2:
  470.       uprintf(fmt, (unsigned short)delta);
  471.       break;
  472.     case 4:
  473.       uprintf(fmt, (unsigned long)delta);
  474.       break;
  475.   }
  476. }
  477.  
  478. /*------------------------------------------------------------------------*/
  479.  
  480. static const char *reg_names[3][8]={
  481.   {"al","cl","dl","bl","ah","ch","dh","bh"},
  482.   {"ax","cx","dx","bx","sp","bp","si","di"},
  483.   {"eax","ecx","edx","ebx","esp","ebp","esi","edi"} };
  484.  
  485. static void reg_name(int which, char size)
  486. {
  487.   if (size == 'F')
  488.   {
  489.     uprintf("st(%d)", which);
  490.     return;
  491.   }
  492.   if (((size == 'v') && (opsize == 32)) || (size == 'd'))
  493.   {
  494.     uputchar('e');
  495.   }
  496.   if (size == 'b')
  497.   {
  498.     uputchar("acdbacdb"[which]);
  499.     uputchar("llllhhhh"[which]);
  500.   }
  501.   else
  502.   {
  503.     uputchar("acdbsbsd"[which]);
  504.     uputchar("xxxxppii"[which]);
  505.   }
  506. }
  507.  
  508. /*------------------------------------------------------------------------*/
  509. static int do_sib(int m)
  510. {
  511.   static const char *i_str[] = {
  512.     "+eax", "+ecx", "+edx", "+ebx", "", "+ebp", "+esi", "+edi" };
  513.   int pick_signed = default_pick_sign;
  514.   int s, i, b, extra=0;
  515.   s = ss(sib());
  516.   i = indx(sib());
  517.   b = base(sib());
  518.   if (b == 5)
  519.   {
  520.       if (m == 0)
  521.       {
  522.         ua_str("%p:[");
  523.         ohex('d', 4, 0, addrsize, 1);
  524.       }
  525.       else
  526.       {
  527.         ua_str("%p:[ebp");
  528.         pick_signed |= 2;
  529.       }
  530.   }
  531.   else
  532.   {
  533.     static const char *sib_str[] = {
  534.       "%p:[eax", "%p:[ecx", "%p:[edx", "%p:[ebx", "%p:[esp", 0, "%p:[esi", "%p:[edi" };
  535.     pick_signed |= 2;
  536.     ua_str(sib_str[b]);
  537.     if ((b == i) && (b != 4) && (i != 5))
  538.       extra = 1;
  539.   }
  540.   if (extra == 0)
  541.   {
  542.     pick_signed |= 2;
  543.     uprintf(i_str[i]);
  544.   }
  545.   if (i != 4 && s)
  546.     uprintf("*%d", (1<<s)+extra);
  547.   return pick_signed;
  548. }
  549.  
  550. /*------------------------------------------------------------------------*/
  551.  
  552. static int modrm_extend;
  553.  
  554. static void do_modrm(char t)
  555. {
  556.   int m = mod(modrm());
  557.   int r = rm(modrm());
  558.   int extend = (addrsize == 32) ? 4 : 2;
  559.   int pick_signed = default_pick_sign;
  560.   if (m == 3)
  561.   {
  562.     reg_name(r, t);
  563.     return;
  564.   }
  565.   if ((m == 0) && (r == 5) && (addrsize == 32))
  566.   {
  567.     ua_str("%p:[");
  568.     ohex('d', extend, 0, addrsize, 0);
  569.     uputchar(']');
  570.     return;
  571.   }
  572.   if ((m == 0) && (r == 6) && (addrsize == 16))
  573.   {
  574.     ua_str("%p:[");
  575.     ohex('w', extend, 0, addrsize, 0);
  576.     uputchar(']');
  577.     return;
  578.   }
  579.   if ((addrsize != 32) || (r != 4))
  580.     ua_str("%p:[");
  581.   if (addrsize == 16)
  582.   {
  583.     static const char *r_str[] = {
  584.       "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" };
  585.     uprintf(r_str[r]);
  586.     pick_signed |= 2;
  587.   }
  588.   else
  589.   {
  590.     if (r == 4)
  591.       pick_signed |= do_sib(m);
  592.     else
  593.     {
  594.       uprintf(reg_names[2][r]);
  595.       pick_signed |= 2;
  596.     }
  597.   }
  598.   modrm_extend = extend;
  599.   ohex("xbv"[m], extend, 1, addrsize, pick_signed);
  600.   uputchar(']');
  601. }
  602.  
  603. /*------------------------------------------------------------------------*/
  604. static void floating_point(int e1)
  605. {
  606.   int esc = e1*8 + reg(modrm());
  607.   if (mod(modrm()) == 3)
  608.   {
  609.     if (fspecial[esc])
  610.     {
  611.       if (fspecial[esc][0] && (fspecial[esc][0][0] == '*'))
  612.       {
  613.         ua_str(fspecial[esc][0]+1);
  614.       }
  615.       else
  616.       {
  617.         ua_str(fspecial[esc][rm(modrm())]);
  618.       }
  619.     }
  620.     else
  621.     {
  622.       ua_str(floatops[esc]);
  623.       ua_str(" %EF");
  624.     }
  625.   }
  626.   else
  627.   {
  628.     ua_str(floatops[esc]);
  629.     ua_str(" %EF");
  630.   }
  631. }
  632.  
  633. /*------------------------------------------------------------------------*/
  634. static void percent(char c, const char **tptr)
  635. {
  636.   word32 vofs, delta;
  637.   char *name;
  638.   int default_signed = default_pick_sign;
  639.   char t = *(*tptr)++, it;
  640.   int extend = (addrsize == 32) ? 4 : 2;
  641.   int iextend;
  642.  
  643.   if (c != '+')
  644.   {
  645.     if (t == '-')
  646.     {
  647.       default_signed = 1;
  648.       t = *(*tptr)++;
  649.     }
  650.     else if (t == '+')
  651.     {
  652.       default_signed = 2;
  653.       t = *(*tptr)++;
  654.     }
  655.   }
  656.   switch (c)
  657.   {
  658.     case 'A':
  659.       ohex(t, extend, 0, addrsize, 0);
  660.       break;
  661.     case 'C':
  662.       uprintf("cr%d", reg(modrm()));
  663.       break;
  664.     case 'D':
  665.       uprintf("dr%d", reg(modrm()));
  666.       break;
  667.     case 'E':
  668.       do_modrm(t);
  669.       break;
  670.     case 'G':
  671.       if (t == 'F')
  672.         reg_name(rm(modrm()), t);
  673.       else
  674.         reg_name(reg(modrm()), t);
  675.       break;
  676.     case 'I':
  677.       it = *(*tptr)++;
  678.       switch (t)
  679.       {
  680.         case 'b':
  681.           iextend = 1;
  682.           break;
  683.         case 'v':
  684.           iextend = extend;
  685.           break;
  686.         default:
  687.           iextend = 0;
  688.           break;
  689.       }
  690.       ohex(it, iextend, 0, opsize, default_signed);
  691.       break;
  692.     case 'J':
  693.       switch (bytes(t))
  694.       {
  695.         case 1:
  696.           vofs = (int8)getbyte();
  697.           break;
  698.         case 2:
  699.           vofs = getbyte();
  700.           vofs += getbyte()<<8;
  701.           vofs = (int16)vofs;
  702.           break;
  703.         case 4:
  704.           vofs = (word32)getbyte();
  705.           vofs |= (word32)getbyte() << 8;
  706.           vofs |= (word32)getbyte() << 16;
  707.           vofs |= (word32)getbyte() << 24;
  708.           break;
  709.         default:
  710.           vofs = 0;    /* To avoid uninit error */
  711.       }
  712.       name = syms_val2name(vofs+vaddr, &delta);
  713.       uprintf("%s", name);
  714.       if (delta)
  715.         uprintf("+%lu (0x%lx %c)", delta, vofs+vaddr,
  716.                 (vofs & 0x80000000UL) ? 0x1e : 0x1f);
  717.       break;
  718.     case 'M':
  719.       do_modrm(t);
  720.       break;
  721.     case 'O':
  722.       ua_str("%p:[");
  723.       ohex(t, extend, 0, addrsize, 0);
  724.       uputchar(']');
  725.       break;
  726.     case 'R':
  727.       do_modrm(t);
  728.       break;
  729.     case 'S':
  730.       uputchar("ecsdfg"[reg(modrm())]);
  731.       uputchar('s');
  732.       break;
  733.     case 'T':
  734.       uprintf("tr%d", reg(modrm()));
  735.       break;
  736.     case 'X':
  737.       uprintf("ds:[");
  738.       if (addrsize == 32)
  739.         uputchar('e');
  740.       uprintf("si]");
  741.       break;
  742.     case 'Y':
  743.       uprintf("es:[");
  744.       if (addrsize == 32)
  745.         uputchar('e');
  746.       uprintf("di]");
  747.       break;
  748.     case '2':
  749.       ua_str(second[getbyte()]);
  750.       break;
  751.     case 'e':
  752.       if (opsize == 32)
  753.       {
  754.         if (t == 'w')
  755.           uputchar('d');
  756.         else
  757.         {
  758.           uputchar('e');
  759.           uputchar(t);
  760.         }
  761.       }
  762.       else
  763.         uputchar(t);
  764.       break;
  765.     case 'f':
  766.       floating_point(t-'0');
  767.       break;
  768.     case 'g':
  769.       ua_str(groups[t-'0'][reg(modrm())]);
  770.       break;
  771.     case 'p':
  772.       switch (t)
  773.       {
  774.         case 'c':
  775.         case 'd':
  776.         case 'e':
  777.         case 'f':
  778.         case 'g':
  779.         case 's':
  780.           prefix = t;
  781.           ua_str(opmap1[getbyte()]);
  782.           break;
  783.         case ':':
  784.           if (prefix)
  785.             uprintf("%cs:", prefix);
  786.           break;
  787.         case ' ':
  788.           ua_str(opmap1[getbyte()]);
  789.           break;
  790.       }
  791.       break;
  792.     case 's':
  793.       switch (t)
  794.       {
  795.         case 'a':
  796.           addrsize = 48 - addrsize;
  797.           ua_str(opmap1[getbyte()]);
  798.           break;
  799.         case 'o':
  800.           opsize = 48 - opsize;
  801.           ua_str(opmap1[getbyte()]);
  802.           break;
  803.       }
  804.       break;
  805.     case '+':
  806.       switch (t)
  807.       {
  808.         case '-':
  809.           default_pick_sign = 1;
  810.           break;
  811.         case '+':
  812.           default_pick_sign = 2;
  813.           break;
  814.         default:
  815.           default_pick_sign = 0;
  816.           break;
  817.       }
  818.   }
  819. }
  820.  
  821. static void ua_str(const char *s)
  822. {
  823.   int c;
  824.   if (s == 0)
  825.   {
  826.     uprintf("<invalid>");
  827.     return;
  828.   }
  829.   while ((c = *s++) != 0)
  830.   {
  831.     if (c == '%')
  832.     {
  833.       c = *s++;
  834.       percent(c, &s);
  835.     }
  836.     else
  837.       if (c == ' ')
  838.         uputchar('\t');
  839.       else
  840.         uputchar(c);
  841.   }
  842. }
  843.  
  844. #ifdef SOURCE_LIST
  845. /*
  846. ** A little brute force hacking and hey presto! A source debugger!
  847. ** Courtesy of Kent Williams williams@herky.cs.uiowa.edu
  848. **
  849. ** KNOWN BUGS:
  850. ** The program will summarily terminate if you run out
  851. ** of memory while you're looking for all the line offsets.  Since
  852. ** a two thousand line source file only creats an 8K array, and the
  853. ** symbol table goes into virtual memory, this shouldn't happen too
  854. ** often.
  855. **
  856. ** One file is left open for reading indefinitely.
  857. */
  858. #include <stdlib.h>
  859. #include <string.h>
  860. /*
  861. ** keep the source line offsets in virtual memory, so you can
  862. ** debug big programs
  863. */
  864. extern word32 salloc(word32 size);
  865. #define symsput(where,ptr,size)     memput(where,ptr,size)
  866. #define symsget(where,ptr,size)     memget(where,ptr,size)
  867.  
  868. /*
  869. ** for each file encountered, keep an array of line start offsets
  870. ** so you can seek into the file to display the current line.
  871. */
  872. typedef struct {
  873.         char *filename;
  874.         long *offsets;
  875. } line_info;
  876.  
  877. static line_info *files;
  878. static last_file = 0;
  879.  
  880. /*
  881. ** add_file -- add a file to the source line database
  882. */
  883. static int
  884. add_file(char *name) {
  885.         FILE *f = fopen(name,"rb");
  886.         char c;
  887.         long *lines,curpos;
  888.         unsigned curline = 0;
  889.  
  890.         if(!f)
  891.                 return -1;
  892.  
  893.         if (files == 0)
  894.           files = (line_info *)malloc(sizeof(line_info));
  895.         else
  896.           files = realloc(files, (last_file+1) * sizeof(line_info));
  897.  
  898.         files[last_file].filename = (char *)malloc(strlen(name)+1);
  899.         strcpy(files[last_file].filename, name);
  900.  
  901.         /*
  902.         ** build an array of line offsets in real memory.
  903.         */
  904.         lines = malloc(sizeof(long));
  905.         lines[curline++] = curpos = 0L;
  906.  
  907.         while((c = getc(f)) != EOF) {
  908.                 curpos++;
  909.                 if(c == '\n') {
  910.                         lines = realloc(lines,sizeof(long)*(curline+1));
  911.                         lines[curline++] = curpos;
  912.                 }
  913.         }
  914.         /*
  915.         ** now move the whole array into virtual memory
  916.         */
  917.         files[last_file].offsets = lines;
  918.         fclose(f);
  919.  
  920.         last_file++;
  921.         return 0;
  922. }
  923.  
  924. static line_info *
  925. find_file(char *name) {
  926.         int i;
  927.         for(i = 0; i < last_file; i++)
  928.                 if(strcmp(name,files[i].filename) == 0)
  929.                         return &files[i];
  930.         if(add_file(name) == -1)
  931.                         return NULL;
  932.         return find_file(name);
  933. }
  934.  
  935. /*
  936. ** myfopen -- cache the most recently accessed source file
  937. ** so you aren't constantly reopening a new file
  938. */
  939. static FILE *
  940. myfopen(char *name) {
  941.         static char fname[80] = "";
  942.         static FILE *current = NULL;
  943.         if(current != NULL && strcmp(fname,name) == 0)
  944.                         return current;
  945.         if(current != NULL) fclose(current);
  946.         strcpy(fname,name);
  947.         return (current = fopen(name,"rb"));
  948. }
  949.  
  950. /*
  951. ** put_source_line -- print the current source line, along with
  952. ** the line # and file name, if necessary.
  953. */
  954. static void
  955. put_source_line(int fmt,char *name,int line) {
  956.         line_info *current = find_file(name);
  957.         FILE *cur;
  958.         if(current == NULL) {
  959.         regular:
  960.           if(fmt == 0)
  961.                   printf(" (%s#%d):\n", name, line);
  962.           else
  963.                   printf("#%d:\n", line);
  964.         } else {
  965.                 char buf1[70];
  966.                 long offset;
  967.                 if((cur = myfopen(name)) == NULL)
  968.                         goto regular;
  969.                 /*
  970.                 ** get the symbol out of virtual memory
  971.                 */
  972.                 offset = current->offsets[line-1];
  973.                 fseek(cur,offset,0);
  974.                 /*
  975.                 ** truncate line so it fits on screen.
  976.                 */
  977.                 fgets(buf1,sizeof(buf1)-2,cur);
  978.                 if(strchr(buf1,'\n') == NULL)
  979.                         strcat(buf1,"\n");
  980.                 if(fmt == 0)
  981.                         printf(" (%s#%d): %s", name, line,buf1);
  982.                 else
  983.                         printf("#%d: %s",line,buf1);
  984.         }
  985. }
  986.  
  987. #endif
  988.  
  989.  
  990. int last_unassemble_unconditional;
  991. int last_unassemble_jump;
  992. int last_unassemble_extra_lines;
  993.  
  994. word32 unassemble(word32 v, int showregs)
  995. {
  996.   int a,b,n,wi, linenum;
  997.   char *cmp, *brp;
  998.   word8 *wp;
  999.   word32 delta;
  1000.   char *name, *lname;
  1001.  
  1002.   default_pick_sign = 0;
  1003.   ansi(A_yellow);
  1004.   last_unassemble_unconditional = 0;
  1005.   last_unassemble_jump = 0;
  1006.   last_unassemble_extra_lines = 0;
  1007.   name = syms_val2name(v, &delta);
  1008.   if (!delta && (name[0] != '0'))
  1009.   {
  1010.     printf("%s()", name);
  1011.     lname = syms_val2line(v, &linenum, 1);
  1012.     if (lname)
  1013. #ifndef SOURCE_LIST
  1014.       printf(" (%s#%d):\n", lname, linenum);
  1015. #else
  1016.       put_source_line(0,lname,linenum);
  1017. #endif
  1018.     else
  1019.       printf(":\n");
  1020.     last_unassemble_extra_lines++;
  1021.   }
  1022.   else
  1023.   {
  1024.     lname = syms_val2line(v, &linenum, 1);
  1025.     if (lname)
  1026.     {
  1027. #ifndef SOURCE_LIST
  1028.       printf("#%d:\n", linenum);
  1029. #else
  1030.       put_source_line(1,lname,linenum);
  1031. #endif
  1032.       last_unassemble_extra_lines++;
  1033.     }
  1034.   }
  1035.  
  1036.   ansi(A_grey);
  1037.   printf("%08lx: ", v);
  1038. #if 0
  1039.   if (!page_is_valid(v+ARENA) || !page_is_valid(v+5+ARENA))
  1040.   {
  1041.     printf("<bad address>\n");
  1042.     return v;
  1043.   }
  1044. #endif
  1045.  
  1046.   prefix = 0;
  1047.   modrmv = sibv = -1;
  1048.   opsize = addrsize = seg_size;
  1049.   vaddr = v;
  1050.   bufp = bufe = 0;
  1051.   col = 0;
  1052.   ubufp = ubuf;
  1053.   ua_str(opmap1[getbyte()]);
  1054.   do {
  1055.     putchar(' ');
  1056.     col++;
  1057.   } while (col < 15);
  1058.   col += strlen(ubuf);
  1059.   do {
  1060.     uputchar(' ');
  1061.     col++;
  1062.   } while (col < 43);
  1063.  
  1064.   ansi(A_cyan);
  1065.   printf("%s", ubuf);
  1066.   ansi(A_grey);
  1067.  
  1068.   if ((strncmp(ubuf, "jmp ", 4) == 0)
  1069.      || (strncmp(ubuf, "ret", 3) == 0))
  1070.     last_unassemble_unconditional = 1;
  1071.   if (ubuf[0] == 'j')
  1072.     last_unassemble_jump = 1;
  1073.  
  1074.   if (!showregs)
  1075.   {
  1076.     putchar('\n');
  1077.     return vaddr;
  1078.   }
  1079.  
  1080.   col -= 43; /* total 25 columns left */
  1081.   wp = (word8 *)&(a_tss.tss_eax);
  1082.   cmp = strchr(ubuf+8, ',');
  1083.   brp = strchr(ubuf+8, '[');
  1084.   if (!cmp) cmp = ubuf+8;
  1085.   if (!brp) brp = ubufp;
  1086.   if (brp < cmp) cmp = brp;
  1087.   if (strncmp(ubuf, "mov ", 4))
  1088.     cmp = ubuf+8;
  1089.   for (b=0; b<8; b++)
  1090.   {
  1091.     for (a=2; a>=0; a--)
  1092.     {
  1093.       n = (a==0) ? 1 : ((a==1) ? 2 : 4);
  1094.       if (strstr(cmp, reg_names[a][b]))
  1095.       {
  1096.         col += strlen(reg_names[a][b])+n*2+2;
  1097.         if (col > 29)
  1098.         {
  1099.           printf("\n%53s", "");
  1100.           col = 0;
  1101.         }
  1102.         printf("%s=", reg_names[a][b]);
  1103.         if (a == 0)
  1104.           wi = (b&3)*4 + (b>>2);
  1105.         else
  1106.           wi = b*4;
  1107.         while (n)
  1108.         {
  1109.           n--;
  1110.           printf("%02x", wp[wi+n]);
  1111.         }
  1112.         putchar(' ');
  1113.         break;
  1114.       }
  1115.     }
  1116.   }
  1117.   putchar('\n');
  1118.   return vaddr;
  1119. }
  1120.