;include file for __dislib.asm and maybe even for your module

;dis_immoperand_t.__flags
di_signextended equ     01h             ;set if imm is sign-extended

;an immediate operand (byte/word/dword)
struc   dis_immoperand_t
  immediate     dd      ?               ;byte/word/dword (check ../.flags)
  __flags       db      ?
ends    dis_immoperand_t

;for dis_regoperand_t.register and more
dr_eax          equ     00h
dr_ecx          equ     01h
dr_edx          equ     02h
dr_ebx          equ     03h
dr_esp          equ     04h
dr_ebp          equ     05h
dr_esi          equ     06h
dr_edi          equ     07h
dr_ax           equ     08h             ;NOTE: dr_ax-dr_di and dr_eax-dr_edi
dr_cx           equ     09h             ; must be the first 10h equates.
dr_dx           equ     0Ah             ; Two of them must fit in a byte
dr_bx           equ     0Bh             ; in dis_memoperand_t.baseindex
dr_sp           equ     0Ch
dr_bp           equ     0Dh
dr_si           equ     0Eh
dr_di           equ     0Fh
dr_al           equ     10h
dr_cl           equ     11h
dr_dl           equ     12h
dr_bl           equ     13h
dr_ah           equ     14h
dr_ch           equ     15h
dr_dh           equ     16h
dr_bh           equ     17h
dr_es           equ     18h             ;not segment overrides!
dr_cs           equ     19h
dr_ss           equ     1Ah
dr_ds           equ     1Bh
dr_fs           equ     1Ch
dr_gs           equ     1Dh
dr_?1           equ     1Eh
dr_?2           equ     1Fh
dr_cr0          equ     20h
dr_cr1          equ     21h
dr_cr2          equ     22h
dr_cr3          equ     23h
dr_cr4          equ     24h
dr_cr5          equ     25h
dr_cr6          equ     26h
dr_cr7          equ     27h
dr_dr0          equ     28h
dr_dr1          equ     29h
dr_dr2          equ     2Ah
dr_dr3          equ     2Bh
dr_dr4          equ     2Ch
dr_dr5          equ     2Dh
dr_dr6          equ     2Eh
dr_dr7          equ     2Fh
dr_tr0          equ     30h
dr_tr1          equ     31h
dr_tr2          equ     32h
dr_tr3          equ     33h
dr_tr4          equ     34h
dr_tr5          equ     35h
dr_tr6          equ     36h
dr_tr7          equ     37h
dr_mm0          equ     38h
dr_mm1          equ     39h
dr_mm2          equ     3Ah
dr_mm3          equ     3Bh
dr_mm4          equ     3Ch
dr_mm5          equ     3Dh
dr_mm6          equ     3Eh
dr_mm7          equ     3Fh
dr_st0          equ     40h
dr_st1          equ     41h
dr_st2          equ     42h
dr_st3          equ     43h
dr_st4          equ     44h
dr_st5          equ     45h
dr_st6          equ     46h
dr_st7          equ     47h
dr_st           equ     48h
dr_none         equ     0FFh            ;Never returned in a struc

;any register
struc   dis_regoperand_t
  register      db      ?
ends    dis_regoperand_t

;dis_memoperand_t.__flags
dm_displbyte    equ     00h             ;displacement size
dm_displword    equ     01h
dm_displdword   equ     02h
dm_displsizemask equ    03h
dm_displsignextended equ 4h             ;if displacement is sign-extended
dm_segoverride  equ     08h             ;if there is a segment override
dm_hasdispl     equ     10h             ;if we have a displacement
dm_hasbase      equ     20h             ;if we have a base register
dm_hasindex     equ     40h             ;if we have an index register
dm_hasscale     equ     80h             ;if we have a scale value

;for dis_memoperand_t.segoverride
dm_seges        equ     00h             ;segment overrides
dm_segcs        equ     01h
dm_segss        equ     02h
dm_segds        equ     03h
dm_segfs        equ     04h
dm_seggs        equ     05h
dm_seg?1        equ     06h
dm_seg?2        equ     07h

;for dis_memoperand_t.scalesize
dm_scale0       equ     00h             ;index scale (bits 0-1)
dm_scale1       equ     01h
dm_scale2       equ     02h
dm_scale3       equ     03h

;any memory address seg:[base+index*X+displ]
struc   dis_memoperand_t
  displ         dd      ?
  baseindex     db      ?               ;base=bits 0-3,index=bits 4-7
  scale         db      ?
  __flags       db      ?
  ;if __flags AND dm_segoverride ne 00h:
  ;current segment override = bits 0-3 (dm_segXX) (ds:[bp] = ds=current seg)
  ;default segment override = bits 4-7 (dm_segXX shl 4) ([bp] = ss=def seg)
  segoverride   db      ?
ends    dis_memoperand_t

;for dis_nearoperand_t.__flags
dn_short        equ     01h             ;jmp short X, loop X, etc X

;call/jmp near/short ptr XXXX
struc   dis_nearoperand_t
  ofs           dd      ?               ;word/dword (check ../.size)
  __flags       db      ?
ends    dis_nearoperand_t

;call/jmp far ptr XXXX:XXXX
struc   dis_faroperand_t
  ofs           dd      ?               ;word/dword (check ../.size)
  seg           dw      ?
ends    dis_faroperand_t

union   dis_operands_t
  imm           dis_immoperand_t ?
  reg           dis_regoperand_t ?
  mem           dis_memoperand_t ?
  nearptr       dis_nearoperand_t ?
  farptr        dis_faroperand_t ?
ends    dis_operands_t

;for dis_operand_t.flags
dop_mem         equ     00h             ;a memory,
dop_imm         equ     01h             ; immediate,
dop_reg         equ     02h             ; register,
dop_nearofs     equ     03h             ; near ptr and
dop_farofs      equ     04h             ; far ptr operand
dop_typemask    equ     07h
dop_small       equ     08h             ;print small (not set if large is)
dop_large       equ     10h             ;print large (not set if small is)

;for dis_operand_t.size (not just memory operands)
dop_sizebyte    equ     00h             ;mov al,[1234h]
dop_sizeword    equ     01h             ;mov ax,[1234h]
dop_sizedword   equ     02h             ;mov eax,[1234h]
dop_sizepword   equ     03h             ;sgdt pword ptr [1234h]
dop_sizeqword   equ     04h             ;fistp qword ptr [1234h]
dop_sizetbyte   equ     05h             ;fbld tbyte ptr [1234h]
dop_sizewordofs equ     06h             ;jmp/call word ptr ds:[1234h] (16-bit)
dop_sizedwordsegofs equ 07h             ;jmp/call dword ptr ds:[1234h] (16-bit)
dop_sizedwordofs equ    08h             ;jmp/call dword ptr ds:[1234h] (32-bit)
dop_sizefwordsegofs equ 09h             ;jmp/call fword ptr ds:[1234h] (32-bit)
dop_sizetwowords equ    0Ah             ;two words in memory (bound)
dop_sizetwodwords equ   0Bh             ;two dwords in memory (bound)

struc   dis_operand_t
  ops           dis_operands_t ?
  flags         dd      ?
  size          db      ?
                db      3 dup (?)
ends    dis_operand_t

if (size dis_operand_t) ne 10h
  err
endif

;for dis_opcode_t.flags (set by __dis:proc, not by you!)
do_hasmodrm     equ     0001h           ;if the instruction has a modR/M byte
do_hassib       equ     0002h           ; and/or a sib byte
do_showmemsize  equ     0004h           ;you should print the memory size
do_dontshowmemsize equ  0008h           ;you shouldn't print the memory size
do_dontprintops equ     0010h           ;don't print the opcodes (string instr.)
do_hasreg       equ     0020h           ;one or more of the operands is a reg
do_hassegreg    equ     0040h           ;one operand has a segment register
do_stringinstruction equ 080h           ;it's a string instruction

;for dis_opcode_t.prefixes (will probably be changed if intel decides
;to add 2 more segment overrides)
__dis_esprefix          equ     01h     ;You shouldn't care about these
__dis_csprefix          equ     02h     ; segment overrides since __dis
__dis_ssprefix          equ     03h     ; will save them in the right
__dis_dsprefix          equ     04h     ; memory operand (if there is a
__dis_fsprefix          equ     05h     ; memory operand, that is!!!)
__dis_gsprefix          equ     06h
__dis_repprefix         equ     08h     ;both __dis_repprefix and
__dis_repnzprefix       equ     10h     ; __dis_repnzprefix are never set
__dis_lockprefix        equ     20h
__dis_opprefix          equ     40h     ;66h (op) or 67h (adr) prefix. Will
__dis_adrprefix         equ     80h     ; not be printed as an operand even
                                        ; if __df_prefixinstructions is set!!!
                                        ; If a 66h or 67h prefix is before
                                        ; any other prefixes, __dis will not
                                        ; print any of those prefixes as an
                                        ; instruction

;for dis_opcode.optype
optype_dunno            equ     00h
optype_far              equ     01h     ;call/jmp far
optype_near             equ     02h     ;call/jmp near
optype_short            equ     03h     ;call/jmp/loop/etc short

;everything in this struc can and will be changed when you call __dis:procptr
struc   dis_opcode_t
  op1           dis_operand_t ?         ;operand 1,
  op2           dis_operand_t ?         ; 2 and
  op3           dis_operand_t ?         ; 3
  flags         dw      ?
  opcodeword    dw      ?               ;00XXh or 0FXXh
  opcodeid      dw      ?               ;see opid_XXX equates (name of instr.)
label   opadrsize word
  opsize        db      ?               ;operand size (16 or 32)
  adrsize       db      ?               ;address size (16 or 32)
label   rmmodrm word
  rm            db      ?               ;the rm field in modR/M
  modrm         db      ?               ;the modR/M byte (if any)
label   regmod word
  reg           db      ?               ;the reg field in modR/M
  mod           db      ?               ;the mod field in modR/M
  sib           db      ?               ;the sib byte (if any)
  noperands     db      ?               ;# of operands. CHECK THIS FIRST!!!!!!
  prefixes      db      ?
  optype        db      ?               ;type of opcode (optype_xxx)
ends    dis_opcode_t

if (size dis_opcode_t) and 3
  err
endif

;for __dis_input_t.flags
__df_prefixinstructions equ 0001h       ;print a prefix as an operand
__df_showsizeop equ     00000002h       ;mov al,[0] -> mov al,small [0] (etc)
__df_stringoperands equ 00000004h       ;expand string instructions + xlat
__df_floatasesc equ     00000008h       ;print float as esc opcodes

;for __dis_input.cputype
__discpu_intel  equ     00h             ;intel 8088+ opcodes
__discpu_amd    equ     01h             ;intel 8088+, AMD and K3D opcodes
__discpu_cyrix  equ     02h             ;intel 8088+ and Cyrix opcodes

struc   __dis_input_t
  opcode        dis_opcode_t ?          ;will be changed in __dis
  eip           dd      ?
  flags         dd      ?
if @codesize
  ;
  ;   Get the next instruction byte
  ;
  ;   input: __dis_gs:si __dis_input_t struc you used as input to __dis:procptr
  ;   output: cf=1=no more bytes left
  ;           cf=0=al=byte
  ;           __dis_gs:si.eip is incremented by one
  ;   registers: al
  ;
  if _wordsize eq 2
    getbyte     dd      ?
  else
    getbyte     df      ?
                dw      ?
  endif
else
  if _wordsize eq 2
    getbyte     dw      ?,?
  else
    getbyte     dd      ?
                dd      ?
  endif
endif
  codesize      db      ?               ;16 or 32-bit code (not changed by me)
  cputype       db      ?
                db      2 dup (?)
ends    __dis_input_t

if (size __dis_input_t) and 3
  err
endif

;input segment to __dis:procptr (__dis_gs:XX)
if @datasize
__dis_gs        equ     gs              ;if far data
else
__dis_gs        equ     ds              ;if near data
endif

        ;decode one instruction (but not print it in a string)
        ;input: __dis_gs:si __dis_input_t struc
        ;output: cf=1=error (__dis_input_t.getbyte returned cf=1)
        ;registers: none
        global  __dis:procptr

;for dis_opcode_t.opcodeid (the HIGH byte). The LOW byte is opcode AND FFh
;for opid_opnames1 and opid_opnames2.
opid_opnames1   equ     0000h           ;opcodes 0000h -> 00FFh
opid_opnames2   equ     0100h           ;opcodes 0F00h -> 0FFFh
opid_grp1EbIbA  equ     0200h           ;0080h
opid_grp1EvIv   equ     0300h           ;0081h
opid_grp1EbIbB  equ     0400h           ;0082h
opid_grp1EvIb   equ     0500h           ;0083h
opid_grp2EbIb   equ     0600h           ;00C0h
opid_grp2EvIb   equ     0700h           ;00C1h
opid_grp2Eb1    equ     0800h           ;00D0h
opid_grp2Ev1    equ     0900h           ;00D1h
opid_grp2EbCL   equ     0A00h           ;00D2h
opid_grp2EvCL   equ     0B00h           ;00D3h
opid_grp3Eb     equ     0C00h           ;00F6h
opid_grp3Ev     equ     0D00h           ;00F7h
opid_grp4       equ     0E00h           ;00FEh
opid_grp5       equ     0F00h           ;00FFh
opid_grp6       equ     1000h           ;0F00h
opid_grp7       equ     1100h           ;0F01h
opid_grp8       equ     1200h           ;0FBAh
opid_grp9       equ     1300h           ;0FC7h
opid_grpA0F71   equ     1400h           ;0F71h
opid_grpA0F72   equ     1500h           ;0F72h
opid_grpA0F73   equ     1600h           ;0F73h
opid_grpB       equ     1700h           ;0FAEh
opid_special    equ     1800h
opid_floatD8reg equ     1900h           ;00D8h with modR/M < C0h (00h-07h)
opid_floatD9reg equ     1A00h
opid_floatDAreg equ     1B00h
opid_floatDBreg equ     1C00h
opid_floatDCreg equ     1D00h
opid_floatDDreg equ     1E00h
opid_floatDEreg equ     1F00h
opid_floatDFreg equ     2000h
opid_floatD8    equ     2100h           ;00D8h with modR/M >= C0h
opid_floatD9    equ     2200h           ; (the lsb in opcode.opcodeid
opid_floatDA    equ     2300h           ; is modR/M-C0h, 00h-3Fh)
opid_floatDB    equ     2400h
opid_floatDC    equ     2500h
opid_floatDD    equ     2600h
opid_floatDE    equ     2700h
opid_floatDF    equ     2800h
;NOTE: If it's a K3D opcode (opid_amdk3d only), opcode.opcodeword
;is 0F00h + last_byte_in_instruction (=K3D opcode), since opcodeword
;is a word. Check high byte of opcodeid if you want to know it's
;a K3D instruction.
opid_amdk3d     equ     2900h           ;0F0FXX opcodes
opid_amdk3dspecial equ  2A00h           ;K3D instructions in normal intel tables
opid_amdspecial equ     2B00h           ;0FXX or XX opcodes
opid_cyrixspecial equ   2C00h           ;Cyrix ops in normal intel table

enum __opid_amdspecial {
  opid_amdsyscall       = opid_amdspecial ;0Fh 05h
  opid_amdsysret                        ;0Fh, 07h
  opid_amdud                            ;0Fh, FFh
  }

enum __opid_amdk3dspecial {
  opid_amdprefetch         = opid_amdk3dspecial ;0Fh, 0Dh, xx000xxx
  opid_amdprefetchw                     ;0Fh, 0Dh, xx001xxx
  opid_amdprefetch2                     ;not used by amd yet
  opid_amdprefetch3                     ;
  opid_amdprefetch4                     ;
  opid_amdprefetch5                     ;
  opid_amdprefetch6                     ;
  opid_amdprefetch7                     ;
  opid_amdfemms                         ;0Fh, 0Eh
  }

enum __opid_cyrixspecial {
  opid_cyrixsvdc                        ;0Fh, 78h
  opid_cyrixrsdc                        ;0Fh, 79h
  opid_cyrixsvldt                       ;0Fh, 7Ah
  opid_cyrixrsldt                       ;0Fh, 7Bh
  opid_cyrixsvts                        ;0Fh, 7Ch
  opid_cyrixrsts                        ;0Fh, 7Dh
                                        ;0Fh, 7Eh moved to 0Fh, 38h
  opid_cyrixrdshr                       ;0Fh, 36h
  opid_cyrixwrshr                       ;0Fh, 37h
  opid_cyrixsmint                       ;0Fh, 38h
  opid_cyrixpaveb                       ;0Fh, 50h
  opid_cyrixpaddsiw                     ;0Fh, 51h
  opid_cyrixpmagw                       ;0Fh, 52h
  opid_cyrixpdistib                     ;0Fh, 54h
  opid_cyrixpsubsiw                     ;0Fh, 55h
  opid_cyrixpmvzb                       ;0Fh, 58h
  opid_cyrixpmulhrw                     ;0Fh, 59h
  opid_cyrixpmvnzb                      ;0Fh, 5Ah
  opid_cyrixpmvlzb                      ;0Fh, 5Bh
  opid_cyrixpmvgezb                     ;0Fh, 5Ch
  opid_cyrixpmulhriw                    ;0Fh, 5Dh
  opid_cyrixpmachriw                    ;0Fh, 5Eh
  }

enum __opid_special {
  opid_db       = opid_special
  opid_enterd
  opid_enterw
  opid_enter
  opid_sgdtd
  opid_sgdtw
  opid_sgdt
  opid_sidtd
  opid_sidtw
  opid_sidt
  opid_lgdtd
  opid_lgdtw
  opid_lgdt
  opid_lidtd
  opid_lidtw
  opid_lidt
  opid_loopdne
  opid_loopwne
  opid_loopne
  opid_loopde
  opid_loopwe
  opid_loope
  opid_loopd
  opid_loopw
  opid_loop
  opid_jcxz
  opid_jecxz
  opid_cbw
  opid_cwde
  opid_cwd
  opid_cdq
  opid_pushad
  opid_pushaw
  opid_pusha
  opid_popad
  opid_popaw
  opid_popa
  opid_pushfd
  opid_pushfw
  opid_pushf
  opid_popfd
  opid_popfw
  opid_popf
  opid_leaved
  opid_leavew
  opid_leave
  opid_iretd
  opid_iretw
  opid_iret
  opid_retnd
  opid_retnw
  opid_retn
  opid_retfd
  opid_retfw
  opid_retf
  opid_xlat
  opid_xlatb
  opid_ins
  opid_insb
  opid_insw
  opid_insd
  opid_outs
  opid_outsb
  opid_outsw
  opid_outsd
  opid_scas
  opid_scasb
  opid_scasw
  opid_scasd
  opid_stos
  opid_stosb
  opid_stosw
  opid_stosd
  opid_lods
  opid_lodsb
  opid_lodsw
  opid_lodsd
  opid_cmps
  opid_cmpsb
  opid_cmpsw
  opid_cmpsd
  opid_movs
  opid_movsb
  opid_movsw
  opid_movsd
  opid_esc
  opid_xchg ;xchg eax,eax in 16-bit code or xchg ax,ax in 32-bit code
  }
