DOSBox-X
|
00001 00002 /* 00003 Ripped out some stuff from the mame releae to only make it for 386's 00004 Changed some variables to use the standard DOSBox data types 00005 Added my callback opcode 00006 00007 */ 00008 00009 /* 00010 * 2asm: Convert binary files to 80*86 assembler. Version 1.00 00011 * Adapted by Andrea Mazzoleni for use with MAME 00012 * HJB 990321: 00013 * Changed output of hex values from 0xxxxh to $xxxx format 00014 * Removed "ptr" from "byte ptr", "word ptr" and "dword ptr" 00015 */ 00016 00017 /* 2asm comments 00018 00019 License: 00020 00021 This program is free software; you can redistribute it and/or modify 00022 it under the terms of the GNU General Public License as published by 00023 the Free Software Foundation. 00024 00025 This program is distributed in the hope that it will be useful, 00026 but WITHOUT ANY WARRANTY; without even the implied warranty of 00027 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00028 GNU General Public License for more details. 00029 00030 Comments: 00031 00032 The code was originally snaffled from the GNU C++ debugger, as ported 00033 to DOS by DJ Delorie and Kent Williams (williams@herky.cs.uiowa.edu). 00034 Extensively modified by Robin Hilliard in Jan and May 1992. 00035 00036 This source compiles under Turbo C v2.01. The disassembler is entirely 00037 table driven so it's fairly easy to change to suit your own tastes. 00038 00039 The instruction table has been modified to correspond with that in 00040 `Programmer's Technical Reference: The Processor and Coprocessor', 00041 Robert L. Hummel, Ziff-Davis Press, 1992. Missing (read "undocumented") 00042 instructions were added and many mistakes and omissions corrected. 00043 00044 00045 Health warning: 00046 00047 When writing and degbugging this code, I didn't have (and still don't have) 00048 a 32-bit disassembler to compare this guy's output with. It's therefore 00049 quite likely that bugs will appear when disassembling instructions which use 00050 the 386 and 486's native 32 bit mode. It seems to work fine in 16 bit mode. 00051 00052 Any comments/updates/bug reports to: 00053 00054 Robin Hilliard, Lough Guitane, Killarney, Co. Kerry, Ireland. 00055 Tel: [+353] 64-54014 00056 Internet: softloft@iruccvax.ucc.ie 00057 Compu$erve: 100042, 1237 00058 00059 If you feel like registering, and possibly get notices of updates and 00060 other items of software, then send me a post card of your home town. 00061 00062 Thanks and enjoy! 00063 00064 */ 00065 #include "dosbox.h" 00066 #if C_DEBUG 00067 #include <stdio.h> 00068 #include <string.h> 00069 #include <stdarg.h> 00070 #include <stdlib.h> 00071 #include "mem.h" 00072 #include "paging.h" 00073 00074 typedef Bit8u UINT8; 00075 typedef Bit16u UINT16; 00076 typedef Bit32u UINT32; 00077 00078 typedef Bit8s INT8; 00079 typedef Bit16s INT16; 00080 typedef Bit32s INT32; 00081 00082 00083 /* Little endian uint read */ 00084 #define le_uint8(ptr) (*(UINT8*)ptr) 00085 00086 INLINE UINT16 le_uint16(const void* ptr) { 00087 const UINT8* ptr8 = (const UINT8*)ptr; 00088 return (UINT16)ptr8[0] | (UINT16)ptr8[1] << 8; 00089 } 00090 INLINE UINT32 le_uint32(const void* ptr) { 00091 const UINT8* ptr8 = (const UINT8*)ptr; 00092 return (UINT32)ptr8[0] | (UINT32)ptr8[1] << 8 | (UINT32)ptr8[2] << 16 | (UINT32)ptr8[3] << 24; 00093 } 00094 00095 /* Little endian int read */ 00096 #define le_int8(ptr) ((INT8)le_uint8(ptr)) 00097 #define le_int16(ptr) ((INT16)le_uint16(ptr)) 00098 #define le_int32(ptr) ((INT32)le_uint32(ptr)) 00099 00100 #define fp_segment(dw) ((dw >> 16) & 0xFFFFU) 00101 #define fp_offset(dw) (dw & 0xFFFFU) 00102 #define fp_addr(seg, off) ( (seg<<4)+off ) 00103 00104 static UINT8 must_do_size; /* used with size of operand */ 00105 static int wordop; /* dealing with word or byte operand */ 00106 00107 static Bit32u instruction_offset; 00108 //static UINT16 instruction_segment; 00109 00110 static char* ubufs; /* start of buffer */ 00111 static char* ubufp; /* last position of buffer */ 00112 static int invalid_opcode = 0; 00113 static int first_space = 1; 00114 00115 static int prefix; /* segment override prefix byte */ 00116 static int modrmv; /* flag for getting modrm byte */ 00117 static int sibv; /* flag for getting sib byte */ 00118 static int opsize; /* just like it says ... */ 00119 static int addrsize; 00120 static int addr32bit=0; 00121 00122 /* some defines for extracting instruction bit fields from bytes */ 00123 00124 #define MOD(a) (((a)>>6)&7) 00125 #define REG(a) (((a)>>3)&7) 00126 #define RM(a) ((a)&7) 00127 #define SCALE(a) (((a)>>6)&7) 00128 #define INDEX(a) (((a)>>3)&7) 00129 #define BASE(a) ((a)&7) 00130 00131 /* Percent tokens in strings: 00132 First char after '%': 00133 A - direct address 00134 C - reg of r/m picks control register 00135 D - reg of r/m picks debug register 00136 E - r/m picks operand 00137 F - flags register 00138 G - reg of r/m picks general register 00139 I - immediate data 00140 J - relative IP offset 00141 + K - call/jmp distance 00142 M - r/m picks memory 00143 O - no r/m, offset only 00144 R - mod of r/m picks register only 00145 S - reg of r/m picks segment register 00146 T - reg of r/m picks test register 00147 X - DS:ESI 00148 Y - ES:EDI 00149 2 - prefix of two-byte opcode 00150 + e - put in 'e' if use32 (second char is part of reg name) 00151 + put in 'w' for use16 or 'd' for use32 (second char is 'w') 00152 + j - put in 'e' in jcxz if prefix==0x66 00153 f - floating point (second char is esc value) 00154 g - do r/m group 'n', n==0..7 00155 p - prefix 00156 s - size override (second char is a,o) 00157 + d - put d if double arg, nothing otherwise (pushfd, popfd &c) 00158 + w - put w if word, d if double arg, nothing otherwise (lodsw/lodsd) 00159 + P - simple prefix 00160 00161 Second char after '%': 00162 a - two words in memory (BOUND) 00163 b - byte 00164 c - byte or word 00165 d - dword 00166 + f - far call/jmp 00167 + n - near call/jmp 00168 p - 32 or 48 bit pointer 00169 + q - byte/word thingy 00170 s - six byte pseudo-descriptor 00171 v - word or dword 00172 w - word 00173 + x - sign extended byte 00174 F - use floating regs in mod/rm 00175 1-8 - group number, esc value, etc 00176 */ 00177 00178 /* watch out for aad && aam with odd operands */ 00179 00180 static char const* (*opmap1)[256]; 00181 00182 static char const * op386map1[256] = { 00183 /* 0 */ 00184 "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev", 00185 "add al,%Ib", "add %eax,%Iv", "push es", "pop es", 00186 "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev", 00187 "or al,%Ib", "or %eax,%Iv", "push cs", "%2 ", 00188 /* 1 */ 00189 "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev", 00190 "adc al,%Ib", "adc %eax,%Iv", "push ss", "pop ss", 00191 "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev", 00192 "sbb al,%Ib", "sbb %eax,%Iv", "push ds", "pop ds", 00193 /* 2 */ 00194 "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev", 00195 "and al,%Ib", "and %eax,%Iv", "%pe", "daa", 00196 "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev", 00197 "sub al,%Ib", "sub %eax,%Iv", "%pc", "das", 00198 /* 3 */ 00199 "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev", 00200 "xor al,%Ib", "xor %eax,%Iv", "%ps", "aaa", 00201 "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev", 00202 "cmp al,%Ib", "cmp %eax,%Iv", "%pd", "aas", 00203 /* 4 */ 00204 "inc %eax", "inc %ecx", "inc %edx", "inc %ebx", 00205 "inc %esp", "inc %ebp", "inc %esi", "inc %edi", 00206 "dec %eax", "dec %ecx", "dec %edx", "dec %ebx", 00207 "dec %esp", "dec %ebp", "dec %esi", "dec %edi", 00208 /* 5 */ 00209 "push %eax", "push %ecx", "push %edx", "push %ebx", 00210 "push %esp", "push %ebp", "push %esi", "push %edi", 00211 "pop %eax", "pop %ecx", "pop %edx", "pop %ebx", 00212 "pop %esp", "pop %ebp", "pop %esi", "pop %edi", 00213 /* 6 */ 00214 "pusha%d ", "popa%d ", "bound %Gv,%Ma", "arpl %Ew,%Rw", 00215 "%pf", "%pg", "%so", "%sa", 00216 "push %Iv", "imul %Gv,%Ev,%Iv","push %Ix", "imul %Gv,%Ev,%Ib", 00217 "insb", "ins%ew", "outsb", "outs%ew", 00218 /* 7 */ 00219 "jo %Jb", "jno %Jb", "jc %Jb", "jnc %Jb", 00220 "je %Jb", "jne %Jb", "jbe %Jb", "ja %Jb", 00221 "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb", 00222 "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb", 00223 /* 8 */ 00224 "%g0 %Eb,%Ib", "%g0 %Ev,%Iv", "%g0 %Eb,%Ib", "%g0 %Ev,%Ix", 00225 "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv", 00226 "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev", 00227 "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev", 00228 /* 9 */ 00229 "nop", "xchg %ecx,%eax", "xchg %edx,%eax", "xchg %ebx,%eax", 00230 "xchg %esp,%eax", "xchg %ebp,%eax", "xchg %esi,%eax", "xchg %edi,%eax", 00231 "cbw", "cwd", "call %Ap", "fwait", 00232 "pushf%d ", "popf%d ", "sahf", "lahf", 00233 /* a */ 00234 "mov al,%Oc", "mov %eax,%Ov", "mov %Oc,al", "mov %Ov,%eax", 00235 "%P movsb", "%P movs%w", "%P cmpsb", "%P cmps%w ", 00236 "test al,%Ib", "test %eax,%Iv", "%P stosb", "%P stos%w ", 00237 "%P lodsb", "%P lods%w ", "%P scasb", "%P scas%w ", 00238 /* b */ 00239 "mov al,%Ib", "mov cl,%Ib", "mov dl,%Ib", "mov bl,%Ib", 00240 "mov ah,%Ib", "mov ch,%Ib", "mov dh,%Ib", "mov bh,%Ib", 00241 "mov %eax,%Iv", "mov %ecx,%Iv", "mov %edx,%Iv", "mov %ebx,%Iv", 00242 "mov %esp,%Iv", "mov %ebp,%Iv", "mov %esi,%Iv", "mov %edi,%Iv", 00243 /* c */ 00244 "%g1 %Eb,%Ib", "%g1 %Ev,%Ib", "ret %Iw", "ret", 00245 "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ib", "mov %Ev,%Iv", 00246 "enter %Iw,%Ib", "leave", "retf %Iw", "retf", 00247 "int 03", "int %Ib", "into", "iret", 00248 /* d */ 00249 "%g1 %Eb,1", "%g1 %Ev,1", "%g1 %Eb,cl", "%g1 %Ev,cl", 00250 "aam ; %Ib", "aad ; %Ib", "setalc", "%P xlat", 00251 #if 0 00252 "esc 0,%Ib", "esc 1,%Ib", "esc 2,%Ib", "esc 3,%Ib", 00253 "esc 4,%Ib", "esc 5,%Ib", "esc 6,%Ib", "esc 7,%Ib", 00254 #else 00255 "%f0", "%f1", "%f2", "%f3", 00256 "%f4", "%f5", "%f6", "%f7", 00257 #endif 00258 /* e */ 00259 "loopne %Jb", "loope %Jb", "loop %Jb", "j%j cxz %Jb", 00260 "in al,%Ib", "in %eax,%Ib", "out %Ib,al", "out %Ib,%eax", 00261 "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Ks%Jb", 00262 "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax", 00263 /* f */ 00264 "lock %p ", "icebp", "repne %p ", "repe %p ", 00265 "hlt", "cmc", "%g2", "%g2", 00266 "clc", "stc", "cli", "sti", 00267 "cld", "std", "%g3", "%g4" 00268 }; 00269 00270 static char const *second[] = { 00271 /* 0 */ 00272 "%g5", "%g6", "lar %Gv,%Ew", "lsl %Gv,%Ew", 00273 0, "[loadall]", "clts", "[loadall]", 00274 "invd", "wbinvd", 0, "UD2", 00275 0, 0, 0, 0, 00276 /* 1 */ 00277 "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev", 00278 0, 0, 0, 0, 00279 0, 0, 0, 0, 00280 0, 0, 0, 0, 00281 /* 2 */ 00282 "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd", 00283 "mov %Rd,%Td", 0, "mov %Td,%Rd", 0, 00284 0, 0, 0, 0, 00285 0, 0, 0, 0, 00286 /* 3 */ 00287 0, "rdtsc", 0, 0, 00288 0, 0, 0, 0, 00289 0, 0, 0, 0, 00290 0, 0, 0, 0, 00291 /* 4 */ 00292 0, 0, 0, 0, 0, 0, 0, 0, 00293 0, 0, 0, 0, 0, 0, 0, 0, 00294 /* 5 */ 00295 0, 0, 0, 0, 0, 0, 0, 0, 00296 0, 0, 0, 0, 0, 0, 0, 0, 00297 /* 6 */ 00298 0, 0, 0, 0, 0, 0, 0, 0, 00299 0, 0, 0, 0, 0, 0, 0, 0, 00300 /* 7 */ 00301 0, 0, 0, 0, 0, 0, 0, 0, 00302 0, 0, 0, 0, 0, 0, 0, 0, 00303 /* 8 */ 00304 "jo %Jv", "jno %Jv", "jb %Jv", "jnb %Jv", 00305 "jz %Jv", "jnz %Jv", "jbe %Jv", "ja %Jv", 00306 "js %Jv", "jns %Jv", "jp %Jv", "jnp %Jv", 00307 "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv", 00308 /* 9 */ 00309 "seto %Eb", "setno %Eb", "setc %Eb", "setnc %Eb", 00310 "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb", 00311 "sets %Eb", "setns %Eb", "setp %Eb", "setnp %Eb", 00312 "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb", 00313 /* a */ 00314 "push fs", "pop fs", "cpuid", "bt %Ev,%Gv", 00315 "shld %Ev,%Gv,%Ib", "shld %Ev,%Gv,cl", 0, 0, 00316 "push gs", "pop gs", 0, "bts %Ev,%Gv", 00317 "shrd %Ev,%Gv,%Ib", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev", 00318 /* b */ 00319 "cmpxchg %Eb,%Gb", "cmpxchg %Ev,%Gv", "lss %Mp", "btr %Ev,%Gv", 00320 "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew", 00321 0, 0, "%g7 %Ev,%Ib", "btc %Ev,%Gv", 00322 "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew", 00323 /* c */ 00324 "xadd %Eb,%Gb", "xadd %Ev,%Gv", 0, 0, 00325 0, 0, 0, 0, 00326 "bswap eax", "bswap ecx", "bswap edx", "bswap ebx", 00327 "bswap esp", "bswap ebp", "bswap esi", "bswap edi", 00328 /* d */ 00329 0, 0, 0, 0, 0, 0, 0, 0, 00330 0, 0, 0, 0, 0, 0, 0, 0, 00331 /* e */ 00332 0, 0, 0, 0, 0, 0, 0, 0, 00333 0, 0, 0, 0, 0, 0, 0, 0, 00334 /* f */ 00335 0, 0, 0, 0, 0, 0, 0, 0, 00336 0, 0, 0, 0, 0, 0, 0, 0, 00337 }; 00338 00339 static char const *groups[][8] = { /* group 0 is group 3 for %Ev set */ 00340 /* 0 */ 00341 { "add", "or", "adc", "sbb", 00342 "and", "sub", "xor", "cmp" }, 00343 /* 1 */ 00344 { "rol", "ror", "rcl", "rcr", 00345 "shl", "shr", "shl", "sar" }, 00346 /* 2 */ /* v v*/ 00347 { "test %Eq,%Iq", "test %Eq,%Iq", "not %Ec", "neg %Ec", 00348 "mul %Ec", "imul %Ec", "div %Ec", "idiv %Ec" }, 00349 /* 3 */ 00350 { "inc %Eb", "dec %Eb", 0, 0, 00351 0, 0, 0, "callback %Iw" }, 00352 /* 4 */ 00353 { "inc %Ev", "dec %Ev", "call %Kn%Ev", "call %Kf%Ep", 00354 "jmp %Kn%Ev", "jmp %Kf%Ep", "push %Ev", 0 }, 00355 /* 5 */ 00356 { "sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew", 00357 "verr %Ew", "verw %Ew", 0, 0 }, 00358 /* 6 */ 00359 { "sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms", 00360 "smsw %Ew", 0, "lmsw %Ew", "invlpg" }, 00361 /* 7 */ 00362 { 0, 0, 0, 0, 00363 "bt", "bts", "btr", "btc" } 00364 }; 00365 00366 /* zero here means invalid. If first entry starts with '*', use st(i) */ 00367 /* no assumed %EFs here. Indexed by RM(modrm()) */ 00368 static char const *f0[] = { 0, 0, 0, 0, 0, 0, 0, 0}; 00369 static char const *fop_8[] = { "*fld st,%GF" }; 00370 static char const *fop_9[] = { "*fxch st,%GF" }; 00371 static char const *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 }; 00372 static char const *fop_11[] = { "*fst st,%GF" }; 00373 static char const *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 }; 00374 static char const *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi", 00375 "fldlg2", "fldln2", "fldz", 0 }; 00376 static char const *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan", 00377 "fxtract", "fprem1", "fdecstp", "fincstp" }; 00378 static char const *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos", 00379 "frndint", "fscale", "fsin", "fcos" }; 00380 static char const *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 }; 00381 static char const *fop_28[] = { "[fneni]", "[fndis]", "fclex", "finit", "[fnsetpm]", "[frstpm]", 0, 0 }; 00382 static char const *fop_32[] = { "*fadd %GF,st" }; 00383 static char const *fop_33[] = { "*fmul %GF,st" }; 00384 static char const *fop_34[] = { "*fcom %GF,st" }; 00385 static char const *fop_35[] = { "*fcomp %GF,st" }; 00386 static char const *fop_36[] = { "*fsubr %GF,st" }; 00387 static char const *fop_37[] = { "*fsub %GF,st" }; 00388 static char const *fop_38[] = { "*fdivr %GF,st" }; 00389 static char const *fop_39[] = { "*fdiv %GF,st" }; 00390 static char const *fop_40[] = { "*ffree %GF" }; 00391 static char const *fop_41[] = { "*fxch %GF" }; 00392 static char const *fop_42[] = { "*fst %GF" }; 00393 static char const *fop_43[] = { "*fstp %GF" }; 00394 static char const *fop_44[] = { "*fucom %GF" }; 00395 static char const *fop_45[] = { "*fucomp %GF" }; 00396 static char const *fop_48[] = { "*faddp %GF,st" }; 00397 static char const *fop_49[] = { "*fmulp %GF,st" }; 00398 static char const *fop_50[] = { "*fcomp %GF,st" }; 00399 static char const *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 }; 00400 static char const *fop_52[] = { "*fsubrp %GF,st" }; 00401 static char const *fop_53[] = { "*fsubp %GF,st" }; 00402 static char const *fop_54[] = { "*fdivrp %GF,st" }; 00403 static char const *fop_55[] = { "*fdivp %GF,st" }; 00404 static char const *fop_56[] = { "*ffreep %GF" }; 00405 static char const *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 }; 00406 00407 static char const **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */ 00408 0, 0, 0, 0, 0, 0, 0, 0, 00409 fop_8, fop_9, fop_10, fop_11, fop_12, fop_13, fop_14, fop_15, 00410 f0, f0, f0, f0, f0, fop_21, f0, f0, 00411 f0, f0, f0, f0, fop_28, f0, f0, f0, 00412 fop_32, fop_33, fop_34, fop_35, fop_36, fop_37, fop_38, fop_39, 00413 fop_40, fop_41, fop_42, fop_43, fop_44, fop_45, f0, f0, 00414 fop_48, fop_49, fop_50, fop_51, fop_52, fop_53, fop_54, fop_55, 00415 fop_56, f0, f0, f0, fop_60, f0, f0, f0, 00416 }; 00417 00418 static const char *floatops[] = { /* assumed " %EF" at end of each. mod != 3 only */ 00419 /*00*/ "fadd", "fmul", "fcom", "fcomp", 00420 "fsub", "fsubr", "fdiv", "fdivr", 00421 /*08*/ "fld", 0, "fst", "fstp", 00422 "fldenv", "fldcw", "fstenv", "fstcw", 00423 /*16*/ "fiadd", "fimul", "ficomw", "ficompw", 00424 "fisub", "fisubr", "fidiv", "fidivr", 00425 /*24*/ "fild", 0, "fist", "fistp", 00426 "frstor", "fldt", 0, "fstpt", 00427 /*32*/ "faddq", "fmulq", "fcomq", "fcompq", 00428 "fsubq", "fsubrq", "fdivq", "fdivrq", 00429 /*40*/ "fldq", 0, "fstq", "fstpq", 00430 0, 0, "fsave", "fstsw", 00431 /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw", 00432 "fisubw", "fisubrw", "fidivw", "fidivr", 00433 /*56*/ "fildw", 0, "fistw", "fistpw", 00434 "fbldt", "fildq", "fbstpt", "fistpq" 00435 }; 00436 00437 static char *addr_to_hex(UINT32 addr, int splitup) { 00438 static char buffer[11]; 00439 00440 if (splitup) { 00441 if (fp_segment(addr)==0 || fp_offset(addr)==0xffff) /* 'coz of wraparound */ 00442 sprintf(buffer, "%04X", (unsigned)fp_offset(addr) ); 00443 else 00444 sprintf(buffer, "%04X:%04X", (unsigned)fp_segment(addr), (unsigned)fp_offset(addr) ); 00445 } else { 00446 #if 0 00447 /* Pet outcommented, reducing address size to 4 00448 when segment is 0 or 0xffff */ 00449 if (fp_segment(addr)==0 || fp_segment(addr)==0xffff) /* 'coz of wraparound */ 00450 sprintf(buffer, "%04X", (unsigned)fp_offset(addr) ); 00451 else 00452 #endif 00453 00454 sprintf(buffer, "%08X", addr ); 00455 00456 } 00457 00458 return buffer; 00459 } 00460 00461 static PhysPt getbyte_mac; 00462 static PhysPt startPtr; 00463 00464 static UINT8 getbyte(void) { 00465 Bit8u c; 00466 00467 if (!mem_readb_checked(getbyte_mac++,&c)) 00468 return c; 00469 00470 return 0xFF; 00471 } 00472 00473 /* 00474 only one modrm or sib byte per instruction, tho' they need to be 00475 returned a few times... 00476 */ 00477 00478 static int modrm(void) 00479 { 00480 if (modrmv == -1) 00481 modrmv = getbyte(); 00482 return modrmv; 00483 } 00484 00485 static int sib(void) 00486 { 00487 if (sibv == -1) 00488 sibv = getbyte(); 00489 return sibv; 00490 } 00491 00492 /*------------------------------------------------------------------------*/ 00493 00494 static void uprintf(char const *s, ...) 00495 { 00496 va_list arg_ptr; 00497 va_start (arg_ptr, s); 00498 vsprintf(ubufp, s, arg_ptr); 00499 va_end(arg_ptr); 00500 while (*ubufp) 00501 ubufp++; 00502 } 00503 00504 static void uputchar(char c) 00505 { 00506 *ubufp++ = c; 00507 *ubufp = 0; 00508 } 00509 00510 /*------------------------------------------------------------------------*/ 00511 00512 static int bytes(char c) 00513 { 00514 switch (c) { 00515 case 'b': 00516 return 1; 00517 case 'w': 00518 return 2; 00519 case 'd': 00520 return 4; 00521 case 'v': 00522 if (opsize == 32) 00523 return 4; 00524 else 00525 return 2; 00526 } 00527 return 0; 00528 } 00529 00530 /*------------------------------------------------------------------------*/ 00531 static void outhex(char subtype, int extend, int optional, int defsize, int sign) 00532 { 00533 int n=0, s=0, i; 00534 INT32 delta = 0; 00535 unsigned char buff[6]; 00536 char signchar; 00537 00538 switch (subtype) { 00539 case 'q': 00540 if (wordop) { 00541 if (opsize==16) { 00542 n = 2; 00543 } else { 00544 n = 4; 00545 } 00546 } else { 00547 n = 1; 00548 } 00549 break; 00550 00551 case 'a': 00552 break; 00553 case 'x': 00554 extend = 2; 00555 n = 1; 00556 break; 00557 case 'b': 00558 n = 1; 00559 break; 00560 case 'w': 00561 n = 2; 00562 break; 00563 case 'd': 00564 n = 4; 00565 break; 00566 case 's': 00567 n = 6; 00568 break; 00569 case 'c': 00570 case 'v': 00571 if (defsize == 32) 00572 n = 4; 00573 else 00574 n = 2; 00575 break; 00576 case 'p': 00577 if (defsize == 32) 00578 n = 6; 00579 else 00580 n = 4; 00581 s = 1; 00582 break; 00583 } 00584 for (i=0; i<n; i++) 00585 buff[i] = getbyte(); 00586 for (; i<extend; i++) 00587 buff[i] = (buff[i-1] & 0x80) ? 0xff : 0; 00588 if (s) { 00589 uprintf("%02X%02X:", (unsigned)buff[n-1], (unsigned)buff[n-2]); 00590 n -= 2; 00591 } 00592 switch (n) { 00593 case 1: 00594 delta = le_int8(buff); 00595 break; 00596 case 2: 00597 delta = le_int16(buff); 00598 break; 00599 case 4: 00600 delta = le_int32(buff); 00601 break; 00602 } 00603 if (extend > n) { 00604 if (subtype!='x') { 00605 if (delta<0) { 00606 delta = -delta; 00607 signchar = '-'; 00608 } else 00609 signchar = '+'; 00610 if (delta || !optional) 00611 uprintf("%c%0*lX", (char)signchar, (int)(extend), (long)delta); 00612 } else { 00613 if (extend==2) 00614 delta = (UINT16)delta; 00615 uprintf("%0.*lX", (int)(2*extend), (long)delta ); 00616 } 00617 return; 00618 } 00619 if ((n == 4) && !sign) { 00620 char *name = addr_to_hex((UINT32)delta, 0); 00621 uprintf("%s", name); 00622 return; 00623 } 00624 switch (n) { 00625 case 1: 00626 if (sign && (char)delta<0) { 00627 delta = -delta; 00628 signchar = '-'; 00629 } else 00630 signchar = '+'; 00631 if (sign) 00632 uprintf("%c%02lX", (char)signchar, delta & 0xFFL); 00633 else 00634 uprintf("%02lX", delta & 0xFFL); 00635 break; 00636 00637 case 2: 00638 if (sign && delta<0) { 00639 signchar = '-'; 00640 delta = -delta; 00641 } else 00642 signchar = '+'; 00643 if (sign) 00644 uprintf("%c%04lX", (char)signchar, delta & 0xFFFFL); 00645 else 00646 uprintf("%04lX", delta & 0xFFFFL); 00647 break; 00648 00649 case 4: 00650 if (sign && delta<0) { 00651 delta = -delta; 00652 signchar = '-'; 00653 } else 00654 signchar = '+'; 00655 if (sign) 00656 uprintf("%c%08lX", (char)signchar, (unsigned long)delta & 0xFFFFFFFFL); 00657 else 00658 uprintf("%08lX", (unsigned long)delta & 0xFFFFFFFFL); 00659 break; 00660 } 00661 } 00662 00663 00664 /*------------------------------------------------------------------------*/ 00665 00666 static void reg_name(int regnum, char size) 00667 { 00668 if (size == 'F') { /* floating point register? */ 00669 uprintf("st(%d)", regnum); 00670 return; 00671 } 00672 if ((((size == 'c') || (size == 'v')) && (opsize == 32)) || (size == 'd')) 00673 uputchar('e'); 00674 if ((size=='q' || size == 'b' || size=='c') && !wordop) { 00675 uputchar("acdbacdb"[regnum]); 00676 uputchar("llllhhhh"[regnum]); 00677 } else { 00678 uputchar("acdbsbsd"[regnum]); 00679 uputchar("xxxxppii"[regnum]); 00680 } 00681 } 00682 00683 00684 /*------------------------------------------------------------------------*/ 00685 00686 static void ua_str(char const *str); 00687 00688 static void do_sib(int m) 00689 { 00690 int s, i, b; 00691 00692 s = SCALE(sib()); 00693 i = INDEX(sib()); 00694 b = BASE(sib()); 00695 switch (b) { /* pick base */ 00696 case 0: ua_str("%p:[eax"); break; 00697 case 1: ua_str("%p:[ecx"); break; 00698 case 2: ua_str("%p:[edx"); break; 00699 case 3: ua_str("%p:[ebx"); break; 00700 case 4: ua_str("%p:[esp"); break; 00701 case 5: 00702 if (m == 0) { 00703 ua_str("%p:["); 00704 outhex('d', 4, 0, addrsize, 0); 00705 } else { 00706 ua_str("%p:[ebp"); 00707 } 00708 break; 00709 case 6: ua_str("%p:[esi"); break; 00710 case 7: ua_str("%p:[edi"); break; 00711 } 00712 switch (i) { /* and index */ 00713 case 0: uprintf("+eax"); break; 00714 case 1: uprintf("+ecx"); break; 00715 case 2: uprintf("+edx"); break; 00716 case 3: uprintf("+ebx"); break; 00717 case 4: break; 00718 case 5: uprintf("+ebp"); break; 00719 case 6: uprintf("+esi"); break; 00720 case 7: uprintf("+edi"); break; 00721 } 00722 if (i != 4) { 00723 switch (s) { /* and scale */ 00724 case 0: /*uprintf("");*/ break; 00725 case 1: uprintf("*2"); break; 00726 case 2: uprintf("*4"); break; 00727 case 3: uprintf("*8"); break; 00728 } 00729 } 00730 } 00731 00732 00733 00734 /*------------------------------------------------------------------------*/ 00735 static void do_modrm(char subtype) 00736 { 00737 int mod = MOD(modrm()); 00738 int rm = RM(modrm()); 00739 int extend = (addrsize == 32) ? 4 : 2; 00740 00741 if (mod == 3) { /* specifies two registers */ 00742 reg_name(rm, subtype); 00743 return; 00744 } 00745 if (must_do_size) { 00746 if (wordop) { 00747 if (addrsize==32 || opsize==32) { /* then must specify size */ 00748 ua_str("dword "); 00749 } else { 00750 ua_str("word "); 00751 } 00752 } else { 00753 ua_str("byte "); 00754 } 00755 } 00756 if ((mod == 0) && (rm == 5) && (addrsize == 32)) {/* mem operand with 32 bit ofs */ 00757 ua_str("%p:["); 00758 outhex('d', extend, 0, addrsize, 0); 00759 uputchar(']'); 00760 return; 00761 } 00762 if ((mod == 0) && (rm == 6) && (addrsize == 16)) { /* 16 bit dsplcmnt */ 00763 ua_str("%p:["); 00764 outhex('w', extend, 0, addrsize, 0); 00765 uputchar(']'); 00766 return; 00767 } 00768 if ((addrsize != 32) || (rm != 4)) 00769 ua_str("%p:["); 00770 if (addrsize == 16) { 00771 switch (rm) { 00772 case 0: uprintf("bx+si"); break; 00773 case 1: uprintf("bx+di"); break; 00774 case 2: uprintf("bp+si"); break; 00775 case 3: uprintf("bp+di"); break; 00776 case 4: uprintf("si"); break; 00777 case 5: uprintf("di"); break; 00778 case 6: uprintf("bp"); break; 00779 case 7: uprintf("bx"); break; 00780 } 00781 } else { 00782 switch (rm) { 00783 case 0: uprintf("eax"); break; 00784 case 1: uprintf("ecx"); break; 00785 case 2: uprintf("edx"); break; 00786 case 3: uprintf("ebx"); break; 00787 case 4: do_sib(mod); break; 00788 case 5: uprintf("ebp"); break; 00789 case 6: uprintf("esi"); break; 00790 case 7: uprintf("edi"); break; 00791 } 00792 } 00793 switch (mod) { 00794 case 1: 00795 outhex('b', extend, 1, addrsize, 0); 00796 break; 00797 case 2: 00798 outhex('v', extend, 1, addrsize, 1); 00799 break; 00800 } 00801 uputchar(']'); 00802 } 00803 00804 00805 00806 /*------------------------------------------------------------------------*/ 00807 static void floating_point(int e1) 00808 { 00809 int esc = e1*8 + REG(modrm()); 00810 00811 if ((MOD(modrm()) == 3)&&fspecial[esc]) { 00812 if (fspecial[esc][0]) { 00813 if (fspecial[esc][0][0] == '*') { 00814 ua_str(fspecial[esc][0]+1); 00815 } else { 00816 ua_str(fspecial[esc][RM(modrm())]); 00817 } 00818 } else { 00819 ua_str(floatops[esc]); 00820 ua_str(" %EF"); 00821 } 00822 } else { 00823 ua_str(floatops[esc]); 00824 ua_str(" %EF"); 00825 } 00826 } 00827 00828 00829 /*------------------------------------------------------------------------*/ 00830 /* Main table driver */ 00831 00832 #define INSTRUCTION_SIZE ( (int)getbyte_mac - (int)startPtr ) 00833 00834 static void percent(char type, char subtype) 00835 { 00836 INT32 vofs = 0; 00837 char *name=NULL; 00838 int extend = (addrsize == 32) ? 4 : 2; 00839 UINT8 c; 00840 00841 switch (type) { 00842 case 'A': /* direct address */ 00843 outhex(subtype, extend, 0, addrsize, 0); 00844 break; 00845 00846 case 'C': /* reg(r/m) picks control reg */ 00847 uprintf("CR%d", REG(modrm())); 00848 must_do_size = 0; 00849 break; 00850 00851 case 'D': /* reg(r/m) picks debug reg */ 00852 uprintf("DR%d", REG(modrm())); 00853 must_do_size = 0; 00854 break; 00855 00856 case 'E': /* r/m picks operand */ 00857 do_modrm(subtype); 00858 break; 00859 00860 case 'G': /* reg(r/m) picks register */ 00861 if (subtype == 'F') /* 80*87 operand? */ 00862 reg_name(RM(modrm()), subtype); 00863 else 00864 reg_name(REG(modrm()), subtype); 00865 must_do_size = 0; 00866 break; 00867 00868 case 'I': /* immed data */ 00869 outhex(subtype, 0, 0, opsize, 0); 00870 break; 00871 00872 case 'J': /* relative IP offset */ 00873 switch (bytes(subtype)) { /* sizeof offset value */ 00874 case 1: 00875 vofs = (INT8)getbyte(); 00876 name = addr_to_hex((UINT32)vofs+(UINT32)instruction_offset+(UINT32)INSTRUCTION_SIZE,0); 00877 break; 00878 case 2: 00879 vofs = (INT32)((UINT32)getbyte()); 00880 vofs |= (INT32)((UINT32)getbyte() << 8); 00881 vofs = (INT16)vofs; 00882 name = addr_to_hex((UINT32)vofs+(UINT32)instruction_offset+(UINT32)INSTRUCTION_SIZE,0); 00883 break; 00884 /* i386 */ 00885 case 4: 00886 vofs = (INT32)((UINT32)getbyte()); /* yuk! */ 00887 vofs |= (INT32)((UINT32)getbyte() << 8); 00888 vofs |= (INT32)((UINT32)getbyte() << 16); 00889 vofs |= (INT32)((UINT32)getbyte() << 24); 00890 name = addr_to_hex((UINT32)vofs+(UINT32)instruction_offset+(UINT32)INSTRUCTION_SIZE,(addrsize == 32)?0:1); 00891 break; 00892 } 00893 if (vofs<0) 00894 uprintf("%s ($-%x)", name, -vofs); 00895 else 00896 uprintf("%s ($+%x)", name, vofs); 00897 break; 00898 00899 case 'K': 00900 switch (subtype) { 00901 case 'f': 00902 ua_str("far "); 00903 break; 00904 case 'n': 00905 ua_str("near "); 00906 break; 00907 case 's': 00908 ua_str("short "); 00909 break; 00910 } 00911 break; 00912 00913 case 'M': /* r/m picks memory */ 00914 do_modrm(subtype); 00915 break; 00916 00917 case 'O': /* offset only */ 00918 ua_str("%p:["); 00919 outhex(subtype, extend, 0, addrsize, 0); 00920 uputchar(']'); 00921 break; 00922 00923 case 'P': /* prefix byte (rh) */ 00924 ua_str("%p:"); 00925 break; 00926 00927 case 'R': /* mod(r/m) picks register */ 00928 reg_name(RM(modrm()), subtype); /* rh */ 00929 must_do_size = 0; 00930 break; 00931 00932 case 'S': /* reg(r/m) picks segment reg */ 00933 uputchar("ecsdfg"[REG(modrm())]); 00934 uputchar('s'); 00935 must_do_size = 0; 00936 break; 00937 00938 case 'T': /* reg(r/m) picks T reg */ 00939 uprintf("tr%d", REG(modrm())); 00940 must_do_size = 0; 00941 break; 00942 00943 case 'X': /* ds:si type operator */ 00944 uprintf("ds:["); 00945 if (addrsize == 32) 00946 uputchar('e'); 00947 uprintf("si]"); 00948 break; 00949 00950 case 'Y': /* es:di type operator */ 00951 uprintf("es:["); 00952 if (addrsize == 32) 00953 uputchar('e'); 00954 uprintf("di]"); 00955 break; 00956 00957 case '2': /* old [pop cs]! now indexes */ 00958 c = getbyte(); 00959 wordop = c & 1; 00960 ua_str(second[c]); /* instructions in 386/486 */ 00961 break; 00962 00963 case 'g': /* modrm group `subtype' (0--7) */ 00964 ua_str(groups[subtype-'0'][REG(modrm())]); 00965 break; 00966 00967 case 'd': /* sizeof operand==dword? */ 00968 if (opsize == 32) 00969 uputchar('d'); 00970 uputchar(subtype); 00971 break; 00972 00973 case 'w': /* insert explicit size specifier */ 00974 if (opsize == 32) 00975 uputchar('d'); 00976 else 00977 uputchar('w'); 00978 uputchar(subtype); 00979 break; 00980 00981 case 'e': /* extended reg name */ 00982 if (opsize == 32) { 00983 if (subtype == 'w') 00984 uputchar('d'); 00985 else { 00986 uputchar('e'); 00987 uputchar(subtype); 00988 } 00989 } else 00990 uputchar(subtype); 00991 break; 00992 00993 case 'f': /* '87 opcode */ 00994 floating_point(subtype-'0'); 00995 break; 00996 00997 case 'j': 00998 if (addrsize==32 || opsize==32) /* both of them?! */ 00999 uputchar('e'); 01000 break; 01001 01002 case 'p': /* prefix byte */ 01003 switch (subtype) { 01004 case 'c': 01005 case 'd': 01006 case 'e': 01007 case 'f': 01008 case 'g': 01009 case 's': 01010 prefix = subtype; 01011 c = getbyte(); 01012 wordop = c & 1; 01013 ua_str((*opmap1)[c]); 01014 break; 01015 case ':': 01016 if (prefix) 01017 uprintf("%cs:", prefix); 01018 break; 01019 case ' ': 01020 c = getbyte(); 01021 wordop = c & 1; 01022 ua_str((*opmap1)[c]); 01023 break; 01024 } 01025 break; 01026 01027 case 's': /* size override */ 01028 switch (subtype) { 01029 case 'a': 01030 addrsize = 48 - addrsize; 01031 c = getbyte(); 01032 wordop = c & 1; 01033 ua_str((*opmap1)[c]); 01034 /* ua_str(opmap1[getbyte()]); */ 01035 break; 01036 case 'o': 01037 opsize = 48 - opsize; 01038 c = getbyte(); 01039 wordop = c & 1; 01040 ua_str((*opmap1)[c]); 01041 /* ua_str(opmap1[getbyte()]); */ 01042 break; 01043 } 01044 break; 01045 } 01046 } 01047 01048 01049 static void ua_str(char const *str) 01050 { 01051 char c; 01052 01053 if (str == 0) { 01054 invalid_opcode = 1; 01055 uprintf("?"); 01056 return; 01057 } 01058 01059 if (strpbrk(str, "CDFGRST")) /* specifiers for registers=>no size 2b specified */ 01060 must_do_size = 0; 01061 01062 while ((c = *str++) != 0) { 01063 if (c == ' ' && first_space) 01064 { 01065 first_space = 0; 01066 do 01067 { 01068 uputchar(' '); 01069 } while ( (int)(ubufp - ubufs) < 5 ); 01070 } 01071 else 01072 if (c == '%') { 01073 c = *str++; 01074 percent(c, *str++); 01075 } else { 01076 uputchar(c); 01077 } 01078 } 01079 } 01080 01081 01082 Bitu DasmI386(char* buffer, PhysPt pc, Bit32u cur_ip, bool bit32) 01083 { 01084 Bitu c; 01085 01086 01087 instruction_offset = cur_ip; 01088 /* input buffer */ 01089 startPtr = pc; 01090 getbyte_mac = pc; 01091 01092 /* output buffer */ 01093 ubufs = buffer; 01094 ubufp = buffer; 01095 first_space = 1; 01096 01097 addr32bit=1; 01098 01099 prefix = 0; 01100 modrmv = sibv = -1; /* set modrm and sib flags */ 01101 if (bit32) opsize = addrsize = 32; 01102 else opsize = addrsize = 16; 01103 c = getbyte(); 01104 wordop = c & 1; 01105 must_do_size = 1; 01106 invalid_opcode = 0; 01107 opmap1=&op386map1; 01108 ua_str(op386map1[c]); 01109 01110 if (invalid_opcode) { 01111 /* restart output buffer */ 01112 ubufp = buffer; 01113 /* invalid instruction, use db xx */ 01114 uprintf("db %02X", (unsigned)c); 01115 return 1; 01116 } 01117 01118 return getbyte_mac-pc; 01119 } 01120 01121 int DasmLastOperandSize() 01122 { 01123 return opsize; 01124 } 01125 01126 01127 #endif 01128