Diff for /np2/i386c/ia32/disasm.c between versions 1.3 and 1.8

version 1.3, 2004/01/23 14:33:26 version 1.8, 2004/07/29 13:06:08
Line 29 Line 29
   
 #include "compiler.h"  #include "compiler.h"
 #include "cpu.h"  #include "cpu.h"
   #include "inst_table.h"
   
   
 /* register strings */  /*
    * register strings
    */
 const char *reg8_str[8] = {  const char *reg8_str[8] = {
         "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"          "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
 };  };
Line 43  const char *reg16_str[8] = {  Line 46  const char *reg16_str[8] = { 
 const char *reg32_str[8] = {   const char *reg32_str[8] = { 
         "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"          "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
 };  };
   
   const char *sreg_str[6] = {
           "es", "cs", "ss", "ds", "fs", "gs"
   };
   
   /*
    * opcode strings
    */
   static const char *opcode_1byte[2][256] = {
   /* 16bit */
   {
   /*00*/  "addb",  "addw",  "addb",  "addw",  "addb",  "addw",  "push",  "pop",
           "orb",   "orw",   "orb",   "orw",   "orb",   "orw",   "push",  NULL,
   /*10*/  "adcb",  "adcw",  "adcb",  "adcw",  "adcb",  "adcw",  "push",  "pop",
           "sbbb",  "sbbw",  "sbbb",  "sbbw",  "sbbb",  "sbbw",  "push",  "pop",
   /*20*/  "andb",  "andw",  "andb",  "andw",  "andb",  "andw",  NULL,    "daa",
           "subb",  "subw",  "subb",  "subw",  "subb",  "subw",  NULL,    "das",
   /*30*/  "xorb",  "xorw",  "xorb",  "xorw",  "xorb",  "xorw",  NULL,    "aaa",
           "cmpb",  "cmpw",  "cmpb",  "cmpw",  "cmpb",  "cmpw",  NULL,    "aas",
   /*40*/  "incw",  "incw",  "incw",  "incw",  "incw",  "incw",  "incw",  "incw",
           "decw",  "decw",  "decw",  "decw",  "decw",  "decw",  "decw",  "decw",
   /*50*/  "push",  "push",  "push",  "push",  "push",  "push",  "push",  "push",
           "pop",   "pop",   "pop",   "pop",   "pop",   "pop",   "pop",   "pop",
   /*60*/  "pusha", "popa",  "bound", "arpl",  NULL,    NULL,    NULL,    NULL,
           "push",  "imul",  "push",  "imul",  "insb",  "insw",  "outsb", "outsw",
   /*70*/  "jo",    "jno",   "jc",    "jnc",   "jz",    "jnz",   "jna",   "ja",
           "js",    "jns",   "jp",    "jnp",   "jl",    "jnl",   "jle",   "jnle",
   /*80*/  NULL,    NULL,    NULL,    NULL,    "testb", "testw", "xchgb", "xchgw",
           "movb",  "movw",  "movb",  "movw",  "movw",  "lea",   "movw",  "pop",
   /*90*/  "nop",   "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw",
           "cbw",   "cwd",   "callf", "fwait", "pushf", "popf",  "sahf",  "lahf",
   /*a0*/  "movb",  "movw",  "movb",  "movw",  "movsb", "movsw", "cmpsb", "cmpsw",
           "testb", "testw", "stosb", "stosw", "lodsb", "lodsw", "scasb", "scasw",
   /*b0*/  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  
           "movw",  "movw",  "movw",  "movw",  "movw",  "movw",  "movw",  "movw",  
   /*c0*/  NULL,    NULL,    "ret",   "ret",   "les",   "lds",   "movb",  "movw",
           "enter", "leave", "retf",  "retf",  "int3",  "int",   "into",  "iret",
   /*d0*/  NULL,    NULL,    NULL,    NULL,    "aam",   "aad",   "salc",  "xlat",
           "esc0",  "esc1",  "esc2",  "esc3",  "esc4",  "esc5",  "esc6",  "esc7",
   /*e0*/  "loopne","loope", "loop",  "jcxz",  "inb",   "inw",   "outb",  "outw",
           "call",  "jmp",   "jmpf",  "jmp",   "inb",   "inw",   "outb",  "outw",
   /*f0*/  "lock:", "int1",  "repne", "repe",  "hlt",   "cmc",   NULL,    NULL,
           "clc",   "stc",   "cli",   "sti",   "cld",   "std",   NULL,    NULL,
   },
   /* 32bit */
   {
   /*00*/  "addb",  "addl",  "addb",  "addl",  "addb",  "addl",  "pushl", "popl",
           "orb",   "orl",   "orb",   "orl",   "orb",   "orl",   "pushl", NULL,
   /*10*/  "adcb",  "adcl",  "adcb",  "adcl",  "adcb",  "adcl",  "pushl", "popl",
           "sbbb",  "sbbl",  "sbbb",  "sbbl",  "sbbb",  "sbbl",  "pushl", "popl",
   /*20*/  "andb",  "andl",  "andb",  "andl",  "andb",  "andl",  NULL,    "daa",
           "subb",  "subl",  "subb",  "subl",  "subb",  "subl",  NULL,    "das",
   /*30*/  "xorb",  "xorl",  "xorb",  "xorl",  "xorb",  "xorl",  NULL,    "aaa",
           "cmpb",  "cmpl",  "cmpb",  "cmpl",  "cmpb",  "cmpl",  NULL,    "aas",
   /*40*/  "incl",  "incl",  "incl",  "incl",  "incl",  "incl",  "incl",  "incl",
           "decl",  "decl",  "decl",  "decl",  "decl",  "decl",  "decl",  "decl",
   /*50*/  "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl",
           "popl",  "popl",  "popl",  "popl",  "popl",  "popl",  "popl",  "pop",
   /*60*/  "pushad","popad", "bound", "arpl",  NULL,    NULL,    NULL,    NULL,
           "pushl", "imul",  "pushl", "imul",  "insb",  "insl",  "outsb", "outsl",
   /*70*/  "jo",    "jno",   "jc",    "jnc",   "jz",    "jnz",   "jna",   "ja",
           "js",    "jns",   "jp",    "jnp",   "jl",    "jnl",   "jle",   "jnle",
   /*80*/  NULL,    NULL,    NULL,    NULL,    "testb", "testl", "xchgb", "xchgl",
           "movb",  "movl",  "movb",  "movl",  "movl",  "lea",   "movl",  "popl",
   /*90*/  "nop",   "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl",
           "cwde",  "cdq",   "callfl","fwait", "pushfd","popfd", "sahf",  "lahf",
   /*a0*/  "movb",  "movl",  "movb",  "movl",  "movsb", "movsd", "cmpsb", "cmpsd",
           "testb", "testl", "stosb", "stosd", "lodsb", "lodsd", "scasb", "scasd",
   /*b0*/  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  "movb",  
           "movl",  "movl",  "movl",  "movl",  "movl",  "movl",  "movl",  "movl",  
   /*c0*/  NULL,    NULL,    "ret",   "ret",   "les",   "lds",   "movb",  "movl",
           "enter", "leave", "retf",  "retf",  "int3",  "int",   "into",  "iretd",
   /*d0*/  NULL,    NULL,    NULL,    NULL,    "aam",   "aad",   "salc",  "xlat",
           "esc0",  "esc1",  "esc2",  "esc3",  "esc4",  "esc5",  "esc6",  "esc7",
   /*e0*/  "loopne","loope", "loop",  "jecxz", "inb",   "inl",   "outb",  "outl",
           "call",  "jmp",   "jmpf",  "jmp",   "inb",   "inl",   "outb",  "outl",
   /*f0*/  "lock:", "int1",  "repne", "repe",  "hlt",   "cmc",   NULL,    NULL,
           "clc",   "stc",   "cli",   "sti",   "cld",   "std",   NULL,    NULL,
   }
   };
   
   static const char *opcode_2byte[2][256] = {
   /* 16bit */
   {
   /*00*/  NULL,      NULL,      "lar",     "lsl",
           NULL,      "loadall", "clts",    NULL,
           "invd",    "wbinvd",  NULL,      "UD2",
           NULL,      NULL,      NULL,      NULL,
   /*10*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*20*/  "movl",    "movl",    "movl",    "movl",
           "movl",    NULL,      "movl",    NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*30*/  "wrmsr",   "rdtsc",   "rdmsr",   NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*40*/  "cmovo",   "cmovno",  "cmovc",   "cmovnc",
           "cmovz",   "cmovnz",  "cmovna",  "cmova",
           "cmovs",   "cmovns",  "cmovp",   "cmovnp",
           "cmovl",   "cmovnl",  "cmovle",  "cmovnle",
   /*50*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*60*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*70*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*80*/  "jo",      "jno",     "jc",      "jnc",
           "jz",      "jnz",     "jna",     "ja",
           "js",      "jns",     "jp",      "jnp",
           "jl",      "jnl",     "jle",     "jnle",
   /*90*/  "seto",    "setno",   "setc",    "setnc",
           "setz",    "setnz",   "setna",   "seta",
           "sets",    "setns",   "setp",    "setnp",
           "setl",    "setnl",   "setle",   "setnle",
   /*a0*/  "push",    "pop",     "cpuid",   "bt",
           "shldb",   "shldw",   "cmpxchgb","cmpxchgw",
           "push",    "pop",     "rsm",     "bts",
           "shrdb",   "shrdw",   NULL,      "imul",
   /*b0*/  "cmpxchgb","cmpxchgw","lss",     "btr",
           "lfs",     "lgs",     "movzb",   "movzw",
           NULL,      "UD2",     NULL,      "btc",
           "bsf",     "bsr",     "movsb",   "movsw",
   /*c0*/  "xaddb",   "xaddw",   NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           "bswap",   "bswap",   "bswap",   "bswap",
           "bswap",   "bswap",   "bswap",   "bswap",
   /*d0*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*e0*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*f0*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   },
   /* 32bit */
   {
   /*00*/  NULL,      NULL,      "lar",     "lsl",
           NULL,      "loadall", "clts",    NULL,
           "invd",    "wbinvd",  NULL,      "UD2",
           NULL,      NULL,      NULL,      NULL,
   /*10*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*20*/  "movl",    "movl",    "movl",    "movl",
           "movl",    NULL,      "movl",    NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*30*/  "wrmsr",   "rdtsc",   "rdmsr",   NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*40*/  "cmovo",   "cmovno",  "cmovc",   "cmovnc",
           "cmovz",   "cmovnz",  "cmovna",  "cmova",
           "cmovs",   "cmovns",  "cmovp",   "cmovnp",
           "cmovl",   "cmovnl",  "cmovle",  "cmovnle",
   /*50*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*60*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*70*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*80*/  "jo",      "jno",     "jc",      "jnc",
           "jz",      "jnz",     "jna",     "ja",
           "js",      "jns",     "jp",      "jnp",
           "jl",      "jnl",     "jle",     "jnle",
   /*90*/  "seto",    "setno",   "setc",    "setnc",
           "setz",    "setnz",   "setna",   "seta",
           "sets",    "setns",   "setp",    "setnp",
           "setl",    "setnl",   "setle",   "setnle",
   /*a0*/  "push",    "pop",     "cpuid",   "bt",
           "shldb",   "shldl",   "cmpxchgb","cmpxchgl",
           "push",    "pop",     "rsm",     "bts",
           "shrdb",   "shrdl",   NULL,      "imul",
   /*b0*/  "cmpxchgb","cmpxchgd","lss",     "btr",
           "lfs",     "lgs",     "movzbl",  "movzwl",
           NULL,      "UD2",     NULL,      "btc",
           "bsf",     "bsr",     "movsbl",  "movswl",
   /*c0*/  "xaddb",   "xaddl",   NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           "bswapl",  "bswapl",  "bswapl",  "bswapl",
           "bswapl",  "bswapl",  "bswapl",  "bswapl",
   /*d0*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*e0*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   /*f0*/  NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
           NULL,      NULL,      NULL,      NULL,
   }
   };
   
   static const char *opcode_0x8x[2][2][8] = {
   /* 16bit */
   {
           { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" },
           { "addw", "orw", "adcw", "sbbw", "andw", "subw", "xorw", "cmpw" }
   },
   /* 32bit */
   {
           { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" },
           { "addl", "orl", "adcl", "sbbl", "andl", "subl", "xorl", "cmpl" }
   }
   };
   
   static const char *opcode_shift[2][2][8] = {
   /* 16bit */
   {
           { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" },
           { "rolw", "rorw", "rclw", "rcrw", "shlw", "shrw", "shlw", "sarw" }
   },
   /* 32bit */
   {
           { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" },
           { "roll", "rorl", "rcll", "rcrl", "shll", "shrl", "shll", "sarl" }
   },
   };
   
   static const char *opcode_0xf6[2][2][8] = {
   /* 16bit */
   {
           { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" },
           { "testw", "testw", "notw", "negw", "mulw", "imulw", "divw", "idivw" }
   },
   /* 32bit */
   {
           { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" },
           { "testl", "testl", "notl", "negl", "mull", "imull", "divl", "idivl" }
   },
   };
   
   static const char *opcode_0xfe[2][2][8] = {
   /* 16bit */
   {
           { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL },
           { "incw", "decw", "call", "callf", "jmp", "jmpf", "push", NULL }
   },
   /* 32bit */
   {
           { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL },
           { "incl", "decl", "call", "callf", "jmp", "jmpf", "pushl", NULL }
   }
   };
   
   static const char *opcode2_g6[8] = {
           "sldt", "str", "lldt", "ltr", "verr", "verw", NULL, NULL
   };
   
   static const char *opcode2_g7[8] = {
           "sgdt", "sidt", "lgdt", "lidt", "smsw", NULL, "lmsw", "invlpg"
   };
   
   static const char *opcode2_g8[8] = {
           NULL, NULL, NULL, NULL, "bt", "bts", "btr", "btc"
   };
   
   static const char *opcode2_g9[8] = {
           NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL
   };
   
   #if 0
   static const char *sep[2] = { " ", ", " };
   #endif
   
   
   /*
    * fetch memory
    */
   static int
   convert_address(disasm_context_t *ctx)
   {
           UINT32 pde_addr;        /* page directory entry address */
           UINT32 pde;             /* page directory entry */
           UINT32 pte_addr;        /* page table entry address */
           UINT32 pte;             /* page table entry */
           UINT32 addr;
   
           if (CPU_STAT_SREG(CPU_CS_INDEX).valid) {
                   addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + ctx->eip;
                   if (CPU_STAT_PAGING) {
                           pde_addr = CPU_STAT_PDE_BASE + ((addr >> 20) & 0xffc);
                           pde = cpu_memoryread_d(pde_addr);
                           /* XXX: check */
                           pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((addr >> 10) & 0xffc);
                           pte = cpu_memoryread_d(pte_addr);
                           /* XXX: check */
                           addr = (pte & CPU_PTE_BASEADDR_MASK) + (addr & 0x00000fff);
                   }
                   ctx->val = addr;
                   return 0;
           }
           return 1;
   }
   
   static int
   disasm_codefetch_1(disasm_context_t *ctx)
   {
           UINT8 val;
           int rv;
   
           rv = convert_address(ctx);
           if (rv)
                   return rv;
   
           val = cpu_memoryread(ctx->val);
           ctx->val = val;
   
           ctx->opbyte[ctx->nopbytes++] = (UINT8)ctx->val;
           ctx->eip++;
   
           return 0;
   }
   
   #if 0
   static int
   disasm_codefetch_2(disasm_context_t *ctx)
   {
           UINT16 val;
           int rv;
   
           rv = disasm_codefetch_1(ctx);
           if (rv)
                   return rv;
           val = (UINT16)(ctx->val & 0xff);
           rv = disasm_codefetch_1(ctx);
           if (rv)
                   return rv;
           val |= (UINT16)(ctx->val & 0xff) << 8;
   
           ctx->val = val;
           return 0;
   }
   
   static int
   disasm_codefetch_4(disasm_context_t *ctx)
   {
           UINT32 val;
           int rv;
   
           rv = disasm_codefetch_1(ctx);
           if (rv)
                   return rv;
           val = ctx->val & 0xff;
           rv = disasm_codefetch_1(ctx);
           if (rv)
                   return rv;
           val |= (UINT32)(ctx->val & 0xff) << 8;
           rv = disasm_codefetch_1(ctx);
           if (rv)
                   return rv;
           val |= (UINT32)(ctx->val & 0xff) << 16;
           rv = disasm_codefetch_1(ctx);
           if (rv)
                   return rv;
           val |= (UINT32)(ctx->val & 0xff) << 24;
   
           ctx->val = val;
           return 0;
   }
   
   /*
    * get effective address.
    */
   
   static int
   ea16(disasm_context_t *ctx, char *buf, size_t size)
   {
           static const char *ea16_str[8] = {
                   "bx + si", "bx + di", "bp + si", "bp + di",
                   "si", "di", "bp", "bx"
           };
           UINT32 val;
           UINT mod, rm;
           int rv;
   
           mod = (ctx->modrm >> 6) & 3;
           rm = ctx->modrm & 7;
   
           if (mod == 0) {
                   if (rm == 6) {
                           /* disp16 */
                           rv = disasm_codefetch_2(ctx);
                           if (rv)
                                   return rv;
   
                           snprintf(buf, size, "[0x%04x]", ctx->val);
                   } else {
                           snprintf(buf, size, "[%s]", ea16_str[rm]);
                   }
           } else {
                   if (mod == 1) {
                           /* disp8 */
                           rv = disasm_codefetch_1(ctx);
                           if (rv)
                                   return rv;
   
                           val = ctx->val;
                           if (val & 0x80) {
                                   val |= 0xff00;
                           }
                   } else {
                           /* disp16 */
                           rv = disasm_codefetch_2(ctx);
                           if (rv)
                                   return rv;
   
                           val = ctx->val;
                   }
                   snprintf(buf, size, "[%s + 0x%04x]", ea16_str[rm], val);
           }
   
           return 0;
   }
   
   static int
   ea32(disasm_context_t *ctx, char *buf, size_t size)
   {
           char tmp[32];
           UINT count[9];
           UINT32 val;
           UINT mod, rm;
           UINT sib;
           UINT scale;
           UINT idx;
           UINT base;
           int rv;
           int i, n;
   
           memset(count, 0, sizeof(count));
   
           mod = (ctx->modrm >> 6) & 3;
           rm = ctx->modrm & 7;
   
           /* SIB */
           if (rm == 4) {
                   rv = disasm_codefetch_1(ctx);
                   if (rv)
                           return rv;
   
                   sib = ctx->val;
                   scale = (sib >> 6) & 3;
                   idx = (sib >> 3) & 7;
                   base = sib & 7;
   
                   /* base */
                   if (mod == 0 && base == 5) {
                           /* disp32 */
                           rv = disasm_codefetch_4(ctx);
                           if (rv)
                                   return rv;
                           count[8] += ctx->val;
                   } else {
                           count[base]++;
                   }
   
                   /* index & scale */
                   if (idx != 4) {
                           count[idx] += 1 << scale;
                   }
           }
   
           /* MOD/RM */
           if (mod == 0 && rm == 5) {
                   /* disp32 */
                   rv = disasm_codefetch_4(ctx);
                   if (rv)
                           return rv;
                   count[8] += ctx->val;
           } else {
                   /* mod */
                   if (mod == 1) {
                           /* disp8 */
                           rv = disasm_codefetch_1(ctx);
                           if (rv)
                                   return rv;
   
                           val = ctx->val;
                           if (val & 0x80) {
                                   val |= 0xffffff00;
                           }
                           count[8] += val;
                   } else if (mod == 2) {
                           /* disp32 */
                           rv = disasm_codefetch_4(ctx);
                           if (rv)
                                   return rv;
                           count[8] += ctx->val;
                   }
   
                   /* rm */
                   if (rm != 4) {
                           count[rm]++;
                   }
           }
   
           milstr_ncpy(buf, "[", size);
           for (n = 0, i = 0; i < 8; i++) {
                   if (count[i] != 0) {
                           if (n > 0) {
                                   milstr_ncat(buf, " + ", size);
                           }
                           if (count[i] > 1) {
                                   snprintf(tmp, size, "%s * %d",
                                       reg32_str[i], count[i]);
                           } else {
                                   milstr_ncpy(tmp, reg32_str[i], sizeof(tmp));
                           }
                           milstr_ncat(buf, tmp, size);
                           n++;
                   }
           }
           if (count[8] != 0) {
                   if (n > 0) {
                           milstr_ncat(buf, " + ", size);
                   }
                   snprintf(tmp, sizeof(tmp), "0x%08x", count[8]);
                   milstr_ncat(buf, tmp, size);
           }
           milstr_ncat(buf, "]", size);
   
           return 0;
   }
   
   static int
   ea(disasm_context_t *ctx)
   {
           char buf[256];
           char tmp[8];
           size_t len;
           int rv;
   
           memset(buf, 0, sizeof(buf));
   
           if (!ctx->as32)
                   rv = ea16(ctx, buf, sizeof(buf));
           else
                   rv = ea32(ctx, buf, sizeof(buf));
           if (rv)
                   return rv;
   
           if (ctx->narg == 0) {
                   milstr_ncat(ctx->next, sep[0], ctx->remain);
           } else {
                   milstr_ncat(ctx->next, sep[1], ctx->remain);
           }
           len = strlen(ctx->next);
           len = (len < ctx->remain) ? len : ctx->remain;
           ctx->next += len;
           ctx->remain -= len;
   
           ctx->arg[ctx->narg++] = ctx->next;
           if (ctx->useseg) {
                   snprintf(tmp, sizeof(tmp), "%s:", sreg_str[ctx->seg]);
                   milstr_ncat(ctx->next, tmp, ctx->remain);
           }
           milstr_ncat(ctx->next, buf, ctx->remain);
           len = strlen(ctx->next);
           len = (len < ctx->remain) ? len : ctx->remain;
           ctx->next += len;
           ctx->remain -= len;
   
           return 0;
   }
   #endif
   
   /*
    * get opcode
    */
   static int
   op(disasm_context_t *ctx)
   {
           const char *opcode;
           UINT8 op[3];
           int prefix;
           size_t len;
           int rv;
           int i;
   
           for (prefix = 0; prefix < MAX_PREFIX; prefix++) {
                   rv = disasm_codefetch_1(ctx);
                   if (rv)
                           return rv;
   
                   op[0] = (UINT8)(ctx->val & 0xff);
                   if (insttable_info[op[0]] & INST_PREFIX) {
                           if (ctx->prefix == 0)
                                   ctx->prefix = ctx->next;
   
                           switch (op[0]) {
                           case 0x26:      /* ES: */
                           case 0x2e:      /* CS: */
                           case 0x36:      /* SS: */
                           case 0x3e:      /* DS: */
                                   ctx->useseg = TRUE;
                                   ctx->seg = (op[0] >> 3) & 3;
                                   break;
   
                           case 0x64:      /* FS: */
                           case 0x65:      /* GS: */
                                   ctx->useseg = TRUE;
                                   ctx->seg = (op[0] - 0x64) + 4;
                                   break;
   
                           case 0x66:      /* OPSize: */
                                   ctx->op32 = !CPU_INST_OP32;
                                   break;
   
                           case 0x67:      /* AddrSize: */
                                   ctx->as32 = !CPU_INST_AS32;
                                   break;
                           }
                           continue;
                   }
                   break;
           }
           if (prefix == MAX_PREFIX)
                   return 1;
   
           if (ctx->prefix) {
                   for (i = 0; i < prefix - 1; i++) {
                           opcode = opcode_1byte[ctx->op32][ctx->opbyte[i]];
                           if (opcode) {
                                   milstr_ncat(ctx->next, opcode, ctx->remain);
                                   milstr_ncat(ctx->next, " ", ctx->remain);
                           }
                   }
                   len = strlen(ctx->next);
                   len = (len < ctx->remain) ? len : ctx->remain;
                   ctx->next += len;
                   ctx->remain -= len;
           }
   
           ctx->opcode[0] = op[0];
           opcode = opcode_1byte[ctx->op32][op[0]];
           if (opcode == NULL) {
                   rv = disasm_codefetch_1(ctx);
                   if (rv)
                           return rv;
   
                   op[1] = (UINT8)(ctx->val & 0xff);
                   ctx->opcode[1] = op[1];
   
                   switch (op[0]) {
                   case 0x0f:
                           opcode = opcode_2byte[ctx->op32][op[1]];
                           if (opcode == NULL) {
                                   rv = disasm_codefetch_1(ctx);
                                   if (rv)
                                           return rv;
   
                                   op[2] = (UINT8)(ctx->val & 0xff);
                                   ctx->opcode[2] = op[2];
   
                                   switch (op[1]) {
                                   case 0x00:
                                           opcode = opcode2_g6[(op[2]>>3)&7];
                                           ctx->modrm = op[2];
                                           break;
   
                                   case 0x01:
                                           opcode = opcode2_g7[(op[2]>>3)&7];
                                           ctx->modrm = op[2];
                                           break;
   
                                   case 0xba:
                                           opcode = opcode2_g8[(op[2]>>3)&7];
                                           ctx->modrm = op[2];
                                           break;
   
                                   case 0xc7:
                                           opcode = opcode2_g9[(op[2]>>3)&7];
                                           ctx->modrm = op[2];
                                           break;
                                   }
                           }
                           break;
   
                   case 0x80: case 0x81: case 0x82: case 0x83:
                           opcode = opcode_0x8x[ctx->op32][op[0]&1][(op[1]>>3)&7];
                           ctx->modrm = op[1];
                           break;
   
                   case 0xc0: case 0xc1:
                   case 0xd0: case 0xd1: case 0xd2: case 0xd3:
                           opcode = opcode_shift[ctx->op32][op[0]&1][(op[1]>>3)&7];
                           ctx->modrm = op[1];
                           break;
   
                   case 0xf6: case 0xf7:
                           opcode = opcode_0xf6[ctx->op32][op[0]&1][(op[1]>>3)&7];
                           ctx->modrm = op[1];
                           break;
   
                   case 0xfe: case 0xff:
                           opcode = opcode_0xfe[ctx->op32][op[0]&1][(op[1]>>3)&7];
                           ctx->modrm = op[1];
                           break;
                   }
           }
           if (opcode == NULL)
                   return 1;
   
           milstr_ncat(ctx->next, opcode, ctx->remain);
   
           return 0;
   }
   
   /*
    * interface
    */
   int
   disasm(UINT32 *eip, disasm_context_t *ctx)
   {
           int rv;
   
           memset(ctx, 0, sizeof(disasm_context_t));
           ctx->remain = sizeof(ctx->str) - 1;
           ctx->next = ctx->str;
           ctx->prefix = 0;
           ctx->op = 0;
           ctx->arg[0] = 0;
           ctx->arg[1] = 0;
           ctx->arg[2] = 0;
   
           ctx->eip = *eip;
           ctx->op32 = CPU_INST_OP32;
           ctx->as32 = CPU_INST_AS32;
           ctx->seg = -1;
   
           ctx->baseaddr = ctx->eip;
           ctx->pad = ' ';
   
           rv = op(ctx);
           if (rv) {
                   memset(ctx, 0, sizeof(disasm_context_t));
                   return rv;
           }
           *eip = ctx->eip;
   
           return 0;
   }

Removed from v.1.3  
changed lines
  Added in v.1.8


RetroPC.NET-CVS <cvs@retropc.net>