open X86

let string_of_x86mnem = function
| Aaa         -> "aaa"
| Aad         -> "aad"
| Aam         -> "aam"
| Aas         -> "aas"
| Adc         -> "adc"
| Add         -> "add"
| Addpd       -> "addpd"
| Addps       -> "addps"
| Addsd       -> "addsd"
| Addss       -> "addss"
| Addsubpd    -> "addsubpd"
| Addsubps    -> "addsubps"
| And         -> "and"
| Andnpd      -> "andnpd"
| Andnps      -> "andnps"
| Andpd       -> "andpd"
| Andps       -> "andps"
| Arpl        -> "arpl"
| Blendpd     -> "blendpd"
| Blendps     -> "blendps"
| Blendvpd    -> "blendvpd"
| Blendvps    -> "blendvps"
| Bound       -> "bound"
| Bsf         -> "bsf"
| Bsr         -> "bsr"
| Bswap       -> "bswap"
| Bt          -> "bt"
| Btc         -> "btc"
| Btr         -> "btr"
| Bts         -> "bts"
| Call        -> "call"
| CallF       -> "callF"
| Cbw         -> "cbw"
| Cdq         -> "cdq"
| Clc         -> "clc"
| Cld         -> "cld"
| Clflush     -> "clflush"
| Cli         -> "cli"
| Clts        -> "clts"
| Cmc         -> "cmc"
| Cmova       -> "cmova"
| Cmovae      -> "cmovae"
| Cmovb       -> "cmovb"
| Cmovbe      -> "cmovbe"
| Cmovg       -> "cmovg"
| Cmovge      -> "cmovge"
| Cmovl       -> "cmovl"
| Cmovle      -> "cmovle"
| Cmovno      -> "cmovno"
| Cmovnp      -> "cmovnp"
| Cmovns      -> "cmovns"
| Cmovnz      -> "cmovnz"
| Cmovo       -> "cmovo"
| Cmovp       -> "cmovp"
| Cmovs       -> "cmovs"
| Cmovz       -> "cmovz"
| Cmp         -> "cmp"
| Cmppd       -> "cmppd"
| Cmpps       -> "cmpps"
| Cmpsb       -> "cmpsb"
| Cmpsd       -> "cmpsd"
| Cmpss       -> "cmpss"
| Cmpsw       -> "cmpsw"
| Cmpxchg     -> "cmpxchg"
| Cmpxchg8b   -> "cmpxchg8b"
| Comisd      -> "comisd"
| Comiss      -> "comiss"
| Cpuid       -> "cpuid"
| Crc32       -> "crc32"
| Cvtdq2pd    -> "cvtdq2pd"
| Cvtdq2ps    -> "cvtdq2ps"
| Cvtpd2dq    -> "cvtpd2dq"
| Cvtpd2pi    -> "cvtpd2pi"
| Cvtpd2ps    -> "cvtpd2ps"
| Cvtpi2pd    -> "cvtpi2pd"
| Cvtpi2ps    -> "cvtpi2ps"
| Cvtps2dq    -> "cvtps2dq"
| Cvtps2pd    -> "cvtps2pd"
| Cvtps2pi    -> "cvtps2pi"
| Cvtsd2si    -> "cvtsd2si"
| Cvtsd2ss    -> "cvtsd2ss"
| Cvtsi2sd    -> "cvtsi2sd"
| Cvtsi2ss    -> "cvtsi2ss"
| Cvtss2sd    -> "cvtss2sd"
| Cvtss2si    -> "cvtss2si"
| Cvttpd2dq   -> "cvttpd2dq"
| Cvttpd2pi   -> "cvttpd2pi"
| Cvttps2dq   -> "cvttps2dq"
| Cvttps2pi   -> "cvttps2pi"
| Cvttsd2si   -> "cvttsd2si"
| Cvttss2si   -> "cvttss2si"
| Cwd         -> "cwd"
| Cwde        -> "cwde"
| Daa         -> "daa"
| Das         -> "das"
| Dec         -> "dec"
| Div         -> "div"
| Divpd       -> "divpd"
| Divps       -> "divps"
| Divsd       -> "divsd"
| Divss       -> "divss"
| Dppd        -> "dppd"
| Dpps        -> "dpps"
| Emms        -> "emms"
| Enter       -> "enter"
| Extractps   -> "extractps"
| F2xm1       -> "f2xm1"
| Fabs        -> "fabs"
| Fadd        -> "fadd"
| Faddp       -> "faddp"
| Fbld        -> "fbld"
| Fbstp       -> "fbstp"
| Fchs        -> "fchs"
| Fclex       -> "fclex"
| Fcmovb      -> "fcmovb"
| Fcmovbe     -> "fcmovbe"
| Fcmove      -> "fcmove"
| Fcmovnb     -> "fcmovnb"
| Fcmovnbe    -> "fcmovnbe"
| Fcmovne     -> "fcmovne"
| Fcmovnu     -> "fcmovnu"
| Fcmovu      -> "fcmovu"
| Fcom        -> "fcom"
| Fcomi       -> "fcomi"
| Fcomip      -> "fcomip"
| Fcomp       -> "fcomp"
| Fcompp      -> "fcompp"
| Fcos        -> "fcos"
| Fdecstp     -> "fdecstp"
| Fdiv        -> "fdiv"
| Fdivp       -> "fdivp"
| Fdivr       -> "fdivr"
| Fdivrp      -> "fdivrp"
| Ffree       -> "ffree"
| Fiadd       -> "fiadd"
| Ficom       -> "ficom"
| Ficomp      -> "ficomp"
| Fidiv       -> "fidiv"
| Fidivr      -> "fidivr"
| Fild        -> "fild"
| Fimul       -> "fimul"
| Fincstp     -> "fincstp"
| Finit       -> "finit"
| Fist        -> "fist"
| Fistp       -> "fistp"
| Fisttp      -> "fisttp"
| Fisub       -> "fisub"
| Fisubr      -> "fisubr"
| Fld         -> "fld"
| Fld1        -> "fld1"
| Fldcw       -> "fldcw"
| Fldenv      -> "fldenv"
| Fldl2e      -> "fldl2e"
| Fldl2t      -> "fldl2t"
| Fldlg2      -> "fldlg2"
| Fldln2      -> "fldln2"
| Fldpi       -> "fldpi"
| Fldz        -> "fldz"
| Fmul        -> "fmul"
| Fmulp       -> "fmulp"
| Fnop        -> "fnop"
| Fpatan      -> "fpatan"
| Fprem       -> "fprem"
| Fprem1      -> "fprem1"
| Fptan       -> "fptan"
| Frndint     -> "frndint"
| Frstor      -> "frstor"
| Fsave       -> "fsave"
| Fscale      -> "fscale"
| Fsin        -> "fsin"
| Fsincos     -> "fsincos"
| Fsqrt       -> "fsqrt"
| Fst         -> "fst"
| Fstcw       -> "fstcw"
| Fstenv      -> "fstenv"
| Fstp        -> "fstp"
| Fstsw       -> "fstsw"
| Fsub        -> "fsub"
| Fsubp       -> "fsubp"
| Fsubr       -> "fsubr"
| Fsubrp      -> "fsubrp"
| Ftst        -> "ftst"
| Fucom       -> "fucom"
| Fucomi      -> "fucomi"
| Fucomip     -> "fucomip"
| Fucomp      -> "fucomp"
| Fucompp     -> "fucompp"
| Fxam        -> "fxam"
| Fxch        -> "fxch"
| Fxrstor     -> "fxrstor"
| Fxsave      -> "fxsave"
| Fxtract     -> "fxtract"
| Fyl2x       -> "fyl2x"
| Fyl2xp1     -> "fyl2xp1"
| Getsec      -> "getsec"
| Haddpd      -> "haddpd"
| Haddps      -> "haddps"
| Hlt         -> "hlt"
| Hsubpd      -> "hsubpd"
| Hsubps      -> "hsubps"
| Icebp       -> "icebp"
| Idiv        -> "idiv"
| Imul        -> "imul"
| In          -> "in"
| Inc         -> "inc"
| Insb        -> "insb"
| Insd        -> "insd"
| Insertps    -> "insertps"
| Insw        -> "insw"
| Int         -> "int"
| Int3        -> "int3"
| Into        -> "into"
| Invd        -> "invd"
| Invlpg      -> "invlpg"
| Iretd       -> "iretd"
| Iretw       -> "iretw"
| Ja          -> "ja"
| Jae         -> "jae"
| Jb          -> "jb"
| Jbe         -> "jbe"
| Jcxz        -> "jcxz"
| Jecxz       -> "jecxz"
| Jg          -> "jg"
| Jge         -> "jge"
| Jl          -> "jl"
| Jle         -> "jle"
| Jmp         -> "jmp"
| JmpF        -> "jmpF"
| Jno         -> "jno"
| Jnp         -> "jnp"
| Jns         -> "jns"
| Jnz         -> "jnz"
| Jo          -> "jo"
| Jp          -> "jp"
| Js          -> "js"
| Jz          -> "jz"
| Lahf        -> "lahf"
| Lar         -> "lar"
| Lddqu       -> "lddqu"
| Ldmxcsr     -> "ldmxcsr"
| Lds         -> "lds"
| Lea         -> "lea"
| Leave       -> "leave"
| Les         -> "les"
| Lfence      -> "lfence"
| Lfs         -> "lfs"
| Lgdt        -> "lgdt"
| Lgs         -> "lgs"
| Lidt        -> "lidt"
| Lldt        -> "lldt"
| Lmsw        -> "lmsw"
| Lodsb       -> "lodsb"
| Lodsd       -> "lodsd"
| Lodsw       -> "lodsw"
| Loop        -> "loop"
| Loopnz      -> "loopnz"
| Loopz       -> "loopz"
| Lsl         -> "lsl"
| Lss         -> "lss"
| Ltr         -> "ltr"
| Maskmovdqu  -> "maskmovdqu"
| Maskmovq    -> "maskmovq"
| Maxpd       -> "maxpd"
| Maxps       -> "maxps"
| Maxsd       -> "maxsd"
| Maxss       -> "maxss"
| Mfence      -> "mfence"
| Minpd       -> "minpd"
| Minps       -> "minps"
| Minsd       -> "minsd"
| Minss       -> "minss"
| Monitor     -> "monitor"
| Mov         -> "mov"
| Movapd      -> "movapd"
| Movaps      -> "movaps"
| Movd        -> "movd"
| Movddup     -> "movddup"
| Movdq2q     -> "movdq2q"
| Movdqa      -> "movdqa"
| Movdqu      -> "movdqu"
| Movhlps     -> "movhlps"
| Movhpd      -> "movhpd"
| Movhps      -> "movhps"
| Movlhps     -> "movlhps"
| Movlpd      -> "movlpd"
| Movlps      -> "movlps"
| Movmskpd    -> "movmskpd"
| Movmskps    -> "movmskps"
| Movntdq     -> "movntdq"
| Movntdqa    -> "movntdqa"
| Movnti      -> "movnti"
| Movntpd     -> "movntpd"
| Movntps     -> "movntps"
| Movntq      -> "movntq"
| Movq        -> "movq"
| Movq2dq     -> "movq2dq"
| Movsb       -> "movsb"
| Movsd       -> "movsd"
| Movshdup    -> "movshdup"
| Movsldup    -> "movsldup"
| Movss       -> "movss"
| Movsw       -> "movsw"
| Movsx       -> "movsx"
| Movupd      -> "movupd"
| Movups      -> "movups"
| Movzx       -> "movzx"
| Mpsadbw     -> "mpsadbw"
| Mul         -> "mul"
| Mulpd       -> "mulpd"
| Mulps       -> "mulps"
| Mulsd       -> "mulsd"
| Mulss       -> "mulss"
| Mwait       -> "mwait"
| Neg         -> "neg"
| Nop         -> "nop"
| Not         -> "not"
| Or          -> "or"
| Orpd        -> "orpd"
| Orps        -> "orps"
| Out         -> "out"
| Outsb       -> "outsb"
| Outsd       -> "outsd"
| Outsw       -> "outsw"
| Pabsb       -> "pabsb"
| Pabsd       -> "pabsd"
| Pabsw       -> "pabsw"
| Packssdw    -> "packssdw"
| Packsswb    -> "packsswb"
| Packusdw    -> "packusdw"
| Packuswb    -> "packuswb"
| Paddb       -> "paddb"
| Paddd       -> "paddd"
| Paddq       -> "paddq"
| Paddsb      -> "paddsb"
| Paddsw      -> "paddsw"
| Paddusb     -> "paddusb"
| Paddusw     -> "paddusw"
| Paddw       -> "paddw"
| Palignr     -> "palignr"
| Pand        -> "pand"
| Pandn       -> "pandn"
| Pause       -> "pause"
| Pavgb       -> "pavgb"
| Pavgw       -> "pavgw"
| Pblendvb    -> "pblendvb"
| Pblendw     -> "pblendw"
| Pcmpeqb     -> "pcmpeqb"
| Pcmpeqd     -> "pcmpeqd"
| Pcmpeqq     -> "pcmpeqq"
| Pcmpeqw     -> "pcmpeqw"
| Pcmpestri   -> "pcmpestri"
| Pcmpestrm   -> "pcmpestrm"
| Pcmpgtb     -> "pcmpgtb"
| Pcmpgtd     -> "pcmpgtd"
| Pcmpgtq     -> "pcmpgtq"
| Pcmpgtw     -> "pcmpgtw"
| Pcmpistri   -> "pcmpistri"
| Pcmpistrm   -> "pcmpistrm"
| Pextrb      -> "pextrb"
| Pextrd      -> "pextrd"
| Pextrw      -> "pextrw"
| Phaddd      -> "phaddd"
| Phaddsw     -> "phaddsw"
| Phaddw      -> "phaddw"
| Phminposuw  -> "phminposuw"
| Phsubd      -> "phsubd"
| Phsubsw     -> "phsubsw"
| Phsubw      -> "phsubw"
| Pinsrb      -> "pinsrb"
| Pinsrd      -> "pinsrd"
| Pinsrw      -> "pinsrw"
| Pmaddubsw   -> "pmaddubsw"
| Pmaddwd     -> "pmaddwd"
| Pmaxsb      -> "pmaxsb"
| Pmaxsd      -> "pmaxsd"
| Pmaxsw      -> "pmaxsw"
| Pmaxub      -> "pmaxub"
| Pmaxud      -> "pmaxud"
| Pmaxuw      -> "pmaxuw"
| Pminsb      -> "pminsb"
| Pminsd      -> "pminsd"
| Pminsw      -> "pminsw"
| Pminub      -> "pminub"
| Pminud      -> "pminud"
| Pminuw      -> "pminuw"
| Pmovmskb    -> "pmovmskb"
| Pmovsxbd    -> "pmovsxbd"
| Pmovsxbq    -> "pmovsxbq"
| Pmovsxbw    -> "pmovsxbw"
| Pmovsxdq    -> "pmovsxdq"
| Pmovsxwd    -> "pmovsxwd"
| Pmovsxwq    -> "pmovsxwq"
| Pmovzxbd    -> "pmovzxbd"
| Pmovzxbq    -> "pmovzxbq"
| Pmovzxbw    -> "pmovzxbw"
| Pmovzxdq    -> "pmovzxdq"
| Pmovzxwd    -> "pmovzxwd"
| Pmovzxwq    -> "pmovzxwq"
| Pmuldq      -> "pmuldq"
| Pmulhrsw    -> "pmulhrsw"
| Pmulhuw     -> "pmulhuw"
| Pmulhw      -> "pmulhw"
| Pmulld      -> "pmulld"
| Pmullw      -> "pmullw"
| Pmuludq     -> "pmuludq"
| Pop         -> "pop"
| Popad       -> "popad"
| Popaw       -> "popaw"
| Popcnt      -> "popcnt"
| Popfd       -> "popfd"
| Popfw       -> "popfw"
| Por         -> "por"
| Prefetchnta -> "prefetchnta"
| Prefetcht0  -> "prefetcht0"
| Prefetcht1  -> "prefetcht1"
| Prefetcht2  -> "prefetcht2"
| Psadbw      -> "psadbw"
| Pshufb      -> "pshufb"
| Pshufd      -> "pshufd"
| Pshufhw     -> "pshufhw"
| Pshuflw     -> "pshuflw"
| Pshufw      -> "pshufw"
| Psignb      -> "psignb"
| Psignd      -> "psignd"
| Psignw      -> "psignw"
| Pslld       -> "pslld"
| Pslldq      -> "pslldq"
| Psllq       -> "psllq"
| Psllw       -> "psllw"
| Psrad       -> "psrad"
| Psraw       -> "psraw"
| Psrld       -> "psrld"
| Psrldq      -> "psrldq"
| Psrlq       -> "psrlq"
| Psrlw       -> "psrlw"
| Psubb       -> "psubb"
| Psubd       -> "psubd"
| Psubq       -> "psubq"
| Psubsb      -> "psubsb"
| Psubsw      -> "psubsw"
| Psubusb     -> "psubusb"
| Psubusw     -> "psubusw"
| Psubw       -> "psubw"
| Ptest       -> "ptest"
| Punpckhbw   -> "punpckhbw"
| Punpckhdq   -> "punpckhdq"
| Punpckhqdq  -> "punpckhqdq"
| Punpckhwd   -> "punpckhwd"
| Punpcklbw   -> "punpcklbw"
| Punpckldq   -> "punpckldq"
| Punpcklqdq  -> "punpcklqdq"
| Punpcklwd   -> "punpcklwd"
| Push        -> "push"
| Pushad      -> "pushad"
| Pushaw      -> "pushaw"
| Pushfd      -> "pushfd"
| Pushfw      -> "pushfw"
| Pxor        -> "pxor"
| Rcl         -> "rcl"
| Rcpps       -> "rcpps"
| Rcpss       -> "rcpss"
| Rcr         -> "rcr"
| Rdmsr       -> "rdmsr"
| Rdpmc       -> "rdpmc"
| Rdtsc       -> "rdtsc"
| Ret         -> "ret"
| Retf        -> "retf"
| Rol         -> "rol"
| Ror         -> "ror"
| Roundpd     -> "roundpd"
| Roundps     -> "roundps"
| Roundsd     -> "roundsd"
| Roundss     -> "roundss"
| Rsm         -> "rsm"
| Rsqrtps     -> "rsqrtps"
| Rsqrtss     -> "rsqrtss"
| Sahf        -> "sahf"
| Sal         -> "sal"
| Salc        -> "salc"
| Sar         -> "sar"
| Sbb         -> "sbb"
| Scasb       -> "scasb"
| Scasd       -> "scasd"
| Scasw       -> "scasw"
| Seta        -> "seta"
| Setae       -> "setae"
| Setb        -> "setb"
| Setbe       -> "setbe"
| Setg        -> "setg"
| Setge       -> "setge"
| Setl        -> "setl"
| Setle       -> "setle"
| Setno       -> "setno"
| Setnp       -> "setnp"
| Setns       -> "setns"
| Setnz       -> "setnz"
| Seto        -> "seto"
| Setp        -> "setp"
| Sets        -> "sets"
| Setz        -> "setz"
| Sfence      -> "sfence"
| Sgdt        -> "sgdt"
| Shl         -> "shl"
| Shld        -> "shld"
| Shr         -> "shr"
| Shrd        -> "shrd"
| Shufpd      -> "shufpd"
| Shufps      -> "shufps"
| Sidt        -> "sidt"
| Sldt        -> "sldt"
| Smsw        -> "smsw"
| Sqrtpd      -> "sqrtpd"
| Sqrtps      -> "sqrtps"
| Sqrtsd      -> "sqrtsd"
| Sqrtss      -> "sqrtss"
| Stc         -> "stc"
| Std         -> "std"
| Sti         -> "sti"
| Stmxcsr     -> "stmxcsr" 
| Stosb       -> "stosb"
| Stosd       -> "stosd"
| Stosw       -> "stosw"
| Str         -> "str"
| Sub         -> "sub"
| Subpd       -> "subpd"
| Subps       -> "subps"
| Subsd       -> "subsd"
| Subss       -> "subss"
| Syscall     -> "syscall"
| Sysenter    -> "sysenter"
| Sysexit     -> "sysexit"
| Sysret      -> "sysret"
| Test        -> "test"
| Ucomisd     -> "ucomisd"
| Ucomiss     -> "ucomiss"
| Ud2         -> "ud2"
| Unpckhpd    -> "unpckhpd"
| Unpckhps    -> "unpckhps"
| Unpcklpd    -> "unpcklpd"
| Unpcklps    -> "unpcklps"
| Verr        -> "verr"
| Verw        -> "verw"
| Vmcall      -> "vmcall"
| Vmclear     -> "vmclear"
| Vmlaunch    -> "vmlaunch"
| Vmptrld     -> "vmptrld"
| Vmptrst     -> "vmptrst"
| Vmread      -> "vmread"
| Vmresume    -> "vmresume"
| Vmwrite     -> "vmwrite"
| Vmxoff      -> "vmxoff"
| Vmxon       -> "vmxon"
| Wait        -> "wait"
| Wbinvd      -> "wbinvd"
| Wrmsr       -> "wrmsr"
| Xadd        -> "xadd"
| Xlat        -> "xlat"
| Xchg        -> "xchg"
| Xor         -> "xor"
| Xorpd       -> "xorpd"
| Xorps       -> "xorps"

let string_of_x86_reg32 = function
| Eax -> "eax"
| Ecx -> "ecx"
| Edx -> "edx"
| Ebx -> "ebx"
| Esp -> "esp"
| Ebp -> "ebp"
| Esi -> "esi"
| Edi -> "edi"

let string_of_x86_debug_reg = function
| DR0 -> "dr0"
| DR1 -> "dr1"
| DR2 -> "dr2"
| DR3 -> "dr3"
| DR4 -> "dr4"
| DR5 -> "dr5"
| DR6 -> "dr6"
| DR7 -> "dr7"

let string_of_x86_control_reg = function
| CR0 -> "cr0"
| CR1 -> "cr1"
| CR2 -> "cr2"
| CR3 -> "cr3"
| CR4 -> "cr4"
| CR5 -> "cr5"
| CR6 -> "cr6"
| CR7 -> "cr7"

let string_of_x86_reg16 = function
| Ax -> "ax"
| Cx -> "cx"
| Dx -> "dx"
| Bx -> "bx"
| Sp -> "sp"
| Bp -> "bp"
| Si -> "si"
| Di -> "di"

let string_of_x86_reg8 = function
| Al -> "al"
| Cl -> "cl"
| Dl -> "dl"
| Bl -> "bl"
| Ah -> "ah"
| Ch -> "ch"
| Dh -> "dh"
| Bh -> "bh"

let string_of_x86_segreg = function
| ES -> "es"
| CS -> "cs"
| SS -> "ss"
| DS -> "ds"
| FS -> "fs"
| GS -> "gs"

let string_of_x86_fpureg = function
| ST0 -> "st(0)"
| ST1 -> "st(1)"
| ST2 -> "st(2)"
| ST3 -> "st(3)"
| ST4 -> "st(4)"
| ST5 -> "st(5)"
| ST6 -> "st(6)"
| ST7 -> "st(7)"

let string_of_x86_mmxreg = function
| MM0 -> "mm0"
| MM1 -> "mm1"
| MM2 -> "mm2"
| MM3 -> "mm3"
| MM4 -> "mm4"
| MM5 -> "mm5"
| MM6 -> "mm6"
| MM7 -> "mm7"

let string_of_x86_xmmreg = function
| XMM0 -> "xmm0"
| XMM1 -> "xmm1"
| XMM2 -> "xmm2"
| XMM3 -> "xmm3"
| XMM4 -> "xmm4"
| XMM5 -> "xmm5"
| XMM6 -> "xmm6"
| XMM7 -> "xmm7"

let string_of_x86_immediate = function
| Ib(i) -> Printf.sprintf "%02lXh" i
| Id(i) -> Printf.sprintf "%08lXh" i
| Iw(i) -> Printf.sprintf "%04lXh" i

(* This is probably backwards, fixme *)
let string_of_x86_far_target = function
| Ap32(seg,offs) -> Printf.sprintf "%04lX:%08lX" seg offs
| Ap16(seg,offs) -> Printf.sprintf "%04lX:%04lX" seg offs

let string_of_displ x = Printf.sprintf "%08lX" x

let string_of_x86_general_reg = function
| Gb(r) -> string_of_x86_reg8  r
| Gw(r) -> string_of_x86_reg16 r
| Gd(r) -> string_of_x86_reg32 r

let string_of_scalefac = function
| 1 -> "2"
| 2 -> "4"
| 3 -> "8"
(* Changeme *)
| _ -> invalid_arg "string_of_scalefac"

let string_of_memexpr = function
| Mem16(seg,bo,so,dop) -> 
  let bs = match bo  with Some(b) -> [string_of_x86_reg16 b]    | None -> [] in
  let ss = match so  with Some(s) -> bs@[string_of_x86_reg16 s] | None -> bs in
  let ds = match dop with Some(d) -> ss@[string_of_displ d]     | None -> ss in
  let s  = StringUtil.intersperse_string "+" ds in
  string_of_x86_segreg seg^":["^Util.opt_get s^"]"
| Mem32(seg,bo,so,dop) -> 
  let bs = match bo with Some(b) -> [string_of_x86_reg32 b]    | None -> [] in
  let ss = match so with 
  | Some(sr,sf) -> 
    let l = [string_of_x86_reg32 sr] in
    let l = if sf <> 0 then l@[string_of_scalefac sf] else l in  
    bs@[Util.opt_get (StringUtil.intersperse_string "*" l)] 
  | None -> bs in
  let ds = match dop with Some(d) -> ss@[string_of_displ d]     | None -> ss in
  let s  = StringUtil.intersperse_string "+" ds in
  string_of_x86_segreg seg^":["^Util.opt_get s^"]"
  
let string_of_x86_memexpr = function
| Mb(m)  ->    "byte ptr "^string_of_memexpr m
| Mw(m)  ->    "word ptr "^string_of_memexpr m
| Md(m)  ->   "dword ptr "^string_of_memexpr m
| Mf(m)  ->   "fword ptr "^string_of_memexpr m
| Mq(m)  ->   "qword ptr "^string_of_memexpr m
| Mt(m)  ->   "tbyte ptr "^string_of_memexpr m
| Mdq(m) -> "xmmword ptr "^string_of_memexpr m

let string_of_x86operand = function
| GeneralReg(r)   -> string_of_x86_general_reg r
| ControlReg(r)   -> string_of_x86_control_reg r
| DebugReg(r)     -> string_of_x86_debug_reg r
| SegReg(r)       -> string_of_x86_segreg r
| FPUReg(r)       -> string_of_x86_fpureg r
| MMXReg(r)       -> string_of_x86_mmxreg r
| XMMReg(r)       -> string_of_x86_xmmreg r
| JccTarget(jt,_) -> Printf.sprintf "%08lX" jt
| Immediate(i)    -> string_of_x86_immediate i
| Memexpr(m)      -> string_of_x86_memexpr m
| FarTarget(a)    -> string_of_x86_far_target a

let string_of_pref = function
| Lock  -> "lock"
| Repne -> "repne" 
| Rep   -> "rep"

let string_of_x86instr { pref = pref; instr = (m,l) } =
  let p = List.map string_of_pref pref in
  let p = match p with
  | [] -> ""
  | _  -> (Util.opt_get (StringUtil.intersperse_string ", " p))^" "
  in
  let l = List.map string_of_x86operand l in
  match l with
  | [] -> string_of_x86mnem m
  | _  -> p^string_of_x86mnem m^" "^(Util.opt_get (StringUtil.intersperse_string ", " l))
