;       SCCSID = @(#)debdcmd.asm        6.1 90/11/17
;      SCCSID = @(#)debdcmd.asm 13.18 90/04/03
PAGE    ,132
NAME    DEBDCMD
TITLE   DEBDCMD - i286 kernel debugger additions
.286p

;***    DEBDCMD.ASM - Debugger Dump commands
;
;       This file contains of the routines for commands to dump memory,
;       descriptor tables, loadall buffer etc.
;
;

.xlist
        include selxport.inc
        include debseg.inc
        include debmac.inc
        include debequ.inc
        include debinit.inc
        include debdesc.inc
        include debprt.inc
.list

Extern checkchr, FAR

LINES_PER_PAGE          equ     23

DataSegmentStart

str3    db      " linaddr   frame   pteframe  state res Dc Au CD WT Us rW Pn",0
str4    db      " state",0
str5    db      "     ",0

TERSE = 1

Extern DebData,         WORD
Extern RegSA,           WORD
Extern DefMode,         BYTE
Extern DumpAddr,        WORD
Extern LoadAllSav,      WORD
Extern LoadallSaved,    BYTE
Extern CursorColumn,    BYTE
Extern ptrGDT,          WORD
Extern sizeGDT,         WORD
Extern ptrLDT,          WORD
Extern sizeLDT,         WORD
Extern ptrIDT,          WORD
Extern sizeIDT,         WORD

;
; DumpPTE routine flags
;

DP_ALL          equ     01h
DP_NOPTE        equ     02h
DP_PDE          equ     04h

;
; DumpDescTab routine flags
;

DDT_NOPRIVATE   equ     01h
DDT_NOSHARED    equ     02h
DDT_LDT         equ     04h
DDT_ALL         equ     08h
DDT_HUGE        equ     10h

;
; Global register message strings
;

Extern AXmsg,           WORD
Extern EAXmsg,          WORD
Extern BXmsg,           WORD
Extern EBXmsg,          WORD
Extern CXmsg,           WORD
Extern ECXmsg,          WORD
Extern DXmsg,           WORD
Extern EDXmsg,          WORD
Extern SPmsg,           WORD
Extern ESPmsg,          WORD
Extern BPmsg,           WORD
Extern EBPmsg,          WORD
Extern SImsg,           WORD
Extern ESImsg,          WORD
Extern DImsg,           WORD
Extern EDImsg,          WORD
Extern CSmsg,           WORD
Extern DSmsg,           WORD
Extern ESmsg,           WORD
Extern FSmsg,           WORD
Extern GSmsg,           WORD
Extern SSmsg,           WORD
Extern IPmsg,           WORD
Extern EIPmsg,          WORD
Extern Fmsg,            WORD
Extern CR3msg,          WORD
Extern GDTRmsg,         WORD
Extern IDTRmsg,         WORD
Extern TRmsg,           WORD
Extern LDTRmsg,         WORD
Extern IOPLmsg,         WORD
Extern MSWmsg,          WORD
; Extern PrtMSW,          BYTE        LARRYB
Extern PrtFlags,        BYTE
Extern PrtRFVM,         BYTE

;
;       Print a descriptor table entry
;

Static  PrtDesc, LABEL, BYTE
        JumpIfBitSet    DescAccess, DAC_SEG_CTRL, PrtSegDesc
        OutMsgBitF      GateAccess, GA_TYPE, <width GA_TYPE>, TypeMsgs
        CaseJump        GateAccess, GA_TYPE, <width GA_TYPE>
        CaseEntry       D_CALLGATE, PrtGateDesc
        CaseEntry       D_TASKGATE, PrtGateDesc
        CaseEntry       D_TRAPGATE, PrtGateDesc
        CaseEntry       D_INTGATE, PrtGateDesc
        CaseEntry       D_CALLGATE32, PrtGateDesc
        CaseEntry       D_TRAPGATE32, PrtGateDesc
        CaseEntry       D_INTGATE32, PrtGateDesc
        CaseEnd
        OutMsg          BASEmsg
        OutDescBasePtr
        OutBlank
        OutMsg          LIMITmsg
        OutDescLimitPtr
        OutBlank
        OutMsg          DPLmsg
        OutBitFHexPtr   DescAccess, DAC_DPL, <width DAC_DPL>
        OutBlank
        OutMsgIfBitSet  DescAccess, DAC_PRESENT, PRESENTmsg
        OutMsgIfBitClr  DescAccess, DAC_PRESENT, NOTPRESENTmsg
        CaseJump        GateAccess, GA_TYPE, <width GA_TYPE>
        CaseEntry       D_TSS, PrtNotBusyTSS
        CaseEntry       D_TSSBUSY, PrtBusyTSS
        CaseEntry       D_TSS32, PrtNotBusyTSS
        CaseEntry       D_TSSBUSY32, PrtBusyTSS
        CaseEnd
        EndOp

PrtBusyTSS      label   byte
        OutMsg          BUSYmsg
        EndOp

PrtNotBusyTSS   label   byte
        OutMsg          NOTBUSYmsg
        EndOp

PrtGateDesc     label   byte
        OutMsg          SELOFFmsg
        OutWordHexPtr   GateSelector
        OutChar         ":"
        OutGateOffstPtr
IFDEF TERSE
        OutBlanks       3
ELSE
        OutBlanks       4
ENDIF
        JumpIfEnv286    ptd1
        OutBlanks       2
ptd1    label   byte

        OutMsg          DPLmsg
        OutBitFHexPtr   GateAccess, DAC_DPL, <width DAC_DPL>
        OutBlank
        OutMsgIfBitSet  GateAccess, DAC_PRESENT, PRESENTmsg
        OutMsgIfBitClr  GateAccess, DAC_PRESENT, NOTPRESENTmsg
        JumpIfBitF      GateAccess, GA_TYPE, <width GA_TYPE>, \
                        D_CALLGATE, PrtCallGate
        JumpIfBitF      GateAccess, GA_TYPE, <width GA_TYPE>, \
                        D_CALLGATE32, PrtCallGate
        EndOp

PrtCallGate     label   byte
        JumpIfBitF      GateWordCount, GWC_COUNT, <width GWC_COUNT>, 0, ptd3
        JumpIfBitF      GateAccess, GA_TYPE, <width GA_TYPE>, D_CALLGATE, ptd2
        OutChar         "D"
ptd2    label   byte
        OutMsg          WORDCOUNTmsg
        OutBitFHexPtr   GateWordCount, GWC_COUNT, <width GWC_COUNT>
ptd3    label   byte
        EndOp

PrtSegDesc      label   byte
        JumpIfBitSet    DescAccess, DAC_CODE_DATA, PrtCSdesc
        OutMsg          DATAmsg
        OutMsg          BASEmsg
        OutDescBasePtr
        OutBlank
        OutMsg          LIMITmsg
        OutDescLimitPtr
        OutBlank
        OutMsg          DPLmsg
        OutBitFHexPtr   DescAccess, DAC_DPL, <width DAC_DPL>
        OutBlank

        OutMsgIfBitSet  DescAccess, DAC_PRESENT, PRESENTmsg
        OutMsgIfBitClr  DescAccess, DAC_PRESENT, NOTPRESENTmsg
        OutMsgIfBitSet  DescAccess, DAC_WRITEDATA, READWRITEmsg
        OutMsgIfBitClr  DescAccess, DAC_WRITEDATA, READONLYmsg
        OutMsgIfBitSet  DescAccess, DAC_EXPANDDOWN, EXPANDDOWNmsg

IFDEF   TERSE
        OutMsgIfBitClr  DescAccess, DAC_EXPANDDOWN, BLANKmsg
ENDIF
        OutMsgIfBitSet  DescAccess, DAC_ACCESS, ACCESSmsg

IFDEF   TERSE
        OutMsgIfBitClr  DescAccess, DAC_ACCESS, BLANKmsg
ENDIF
        OutMsgIfBitSet  DescAttr, DAT_G, GRAN4Kmsg
        OutMsgIfBitSet  DescAttr, DAT_B, DBIGmsg
        OutMsgIfBitSet  DescAttr, DAT_RES, RESmsg
        OutMsgIfBitSet  DescAttr, DAT_AVAL, UVIRTmsg
        EndOp

PrtCSdesc       label   byte
        OutMsg          CODEmsg
        OutMsg          BASEmsg
        OutDescBasePtr
        OutBlank
        OutMsg          LIMITmsg
        OutDescLimitPtr
        OutBlank
        OutMsg          DPLmsg
        OutBitFHexPtr   DescAccess, DAC_DPL, <width DAC_DPL>
        OutBlank

        OutMsgIfBitSet  DescAccess, DAC_PRESENT, PRESENTmsg
        OutMsgIfBitClr  DescAccess, DAC_PRESENT, NOTPRESENTmsg
        OutMsgIfBitSet  DescAccess, DAC_READCODE, READEXECmsg
        OutMsgIfBitClr  DescAccess, DAC_READCODE, EXECONLYmsg
        OutMsgIfBitSet  DescAccess, DAC_CONFORMING, CONFORMINGmsg

IFDEF   TERSE
        OutMsgIfBitClr  DescAccess, DAC_CONFORMING, BLANKmsg
ENDIF
        OutMsgIfBitSet  DescAccess, DAC_ACCESS, ACCESSmsg

IFDEF   TERSE
        OutMsgIfBitClr  DescAccess, DAC_ACCESS, BLANKmsg
ENDIF
        OutMsgIfBitSet  DescAttr, DAT_G, GRAN4Kmsg
        OutMsgIfBitSet  DescAttr, DAT_D, C32msg
        OutMsgIfBitSet  DescAttr, DAT_RES, RESmsg
        OutMsgIfBitSet  DescAttr, DAT_AVAL, UVIRTmsg
        EndOp

;
;       Print descriptor strings and tables.
;

IFDEF TERSE

Static NOTPRESENTmsg,   STRING, "NP "
Static PRESENTmsg,      STRING, "P  "
Static READWRITEmsg,    STRING, "RW "
Static READONLYmsg,     STRING, "RO "
Static EXPANDDOWNmsg,   STRING, "ED "
Static CONFORMINGmsg,   STRING, "C  "
Static GRAN4Kmsg,       STRING, "G4k "
Static DBIGmsg,         STRING, "BIG "
Static C32msg,          STRING, "C32 "
Static RESmsg,          STRING, "RES "
Static UVIRTmsg,        STRING, "UV"
Static WORDCOUNTmsg,    STRING, "WC="
Static READEXECmsg,     STRING, "RE "
Static EXECONLYmsg,     STRING, "EO "
Static ACCESSmsg,       STRING, "A  "
Static NOTBUSYmsg,      STRING, "NB "
Static BUSYmsg,         STRING, "B  "
Static BLANKmsg,        STRING, "   "
Static SELOFFmsg,       STRING, "Sel:Off="
Static BASEmsg,         STRING, "Bas="
Static LIMITmsg,        STRING, "Lim="

ELSE

Static NOTPRESENTmsg,   STRING, "NotPres "
Static PRESENTmsg,      STRING, "Present "
Static READWRITEmsg,    STRING, "ReadWrite "
Static READONLYmsg,     STRING, "ReadOnly  "
Static EXPANDDOWNmsg,   STRING, "ExpandDown "
Static CONFORMINGmsg,   STRING, "Conform "
Static GRAN4Kmsg,       STRING, "Gran 4k "
Static DBIGmsg,         STRING, "Big "
Static C32msg,          STRING, "C32 "
Static RESmsg,          STRING, "Reserved "
Static UVIRTmsg,        STRING, "UVirt "
Static WORDCOUNTmsg,    STRING, "WordCount="
Static READEXECmsg,     STRING, "ReadExec  "
Static EXECONLYmsg,     STRING, "ExecOnly  "
Static ACCESSmsg,       STRING, "Accessed "
Static NOTBUSYmsg,      BYTE,   "Not "          ; must be together
Static BUSYmsg,         STRING, "Busy"          ;
Static BLANKmsg,        STRING, "    "
Static SELOFFmsg,       STRING, "Sel:Offst="
Static BASEmsg,         STRING, "Base="
Static LIMITmsg,        STRING, "Limit="

ENDIF

Static DPLmsg,          STRING, "DPL="

Static TypeMsgs, LABEL, WORD
        dw      dataOFFSET INVALIDmsg           ; 0
        dw      dataOFFSET TSSmsg               ; 1
        dw      dataOFFSET LDTmsg               ; 2
        dw      dataOFFSET TSSmsg               ; 3
        dw      dataOFFSET CALLGATEmsg          ; 4
        dw      dataOFFSET TASKGATEmsg          ; 5
        dw      dataOFFSET INTGATEmsg           ; 6
        dw      dataOFFSET TRAPGATEmsg          ; 7
        dw      dataOFFSET INVALIDmsg           ; 8
        dw      dataOFFSET TSS32msg             ; 9
        dw      dataOFFSET RESERVEDmsg          ; 10
        dw      dataOFFSET TSS32msg             ; 11
        dw      dataOFFSET CALLGATE32msg        ; 12
        dw      dataOFFSET RESERVEDmsg          ; 13
        dw      dataOFFSET INTGATE32msg         ; 14
        dw      dataOFFSET TRAPGATE32msg        ; 15

Static CODEmsg,         STRING, "Code    "
Static DATAmsg,         STRING, "Data    "
Static INVALIDmsg,      STRING, "Invalid "
Static TSSmsg,          STRING, "TSS     "
Static LDTmsg,          STRING, "LDT     "
Static CALLGATEmsg,     STRING, "CallG   "
Static TASKGATEmsg,     STRING, "TaskG   "
Static INTGATEmsg,      STRING, "IntG    "
Static TRAPGATEmsg,     STRING, "TrapG   "
Static RESERVEDmsg,     STRING, "Reserve "
Static TSS32msg,        STRING, "TSS32   "
Static CALLGATE32msg,   STRING, "CallG32 "
Static INTGATE32msg,    STRING, "IntG32  "
Static TRAPGATE32msg,   STRING, "TrapG32 "

Static Dmsg,  STRING, "D"               ; Dirty
Static cmsg,  STRING, "c"               ; clean
Static Amsg,  STRING, "A"               ; Accessed
Static uamsg, STRING, "u"               ; unaccessed
Static CDmsg, STRING, "CD"              ; Cache Disable
Static WTmsg, STRING, "WT"              ; Write Through
Static blmsg, STRING, "  "              ; blanks
Static Umsg,  STRING, "U"               ; User
Static smsg,  STRING, "s"               ; supervisor
Static Wmsg,  STRING, "W"               ; Writable
Static rmsg,  STRING, "r"               ; read-only
Static Pmsg,  STRING, "P"               ; Present
Static nmsg,  STRING, "n"               ; not present

ifdef OS2                               ; OS/2 specific
Static PteReservedmsg,  STRING, "???"           ; reserved

Static PteInvalidmsg,   STRING, "  invalid"     ; invalid

Static PtePageablemsg,  STRING, "  pageable"    ; Pageable
Static PteResidentmsg,  STRING, "  resident"    ; Resident
Static PteUvirtmsg,     STRING, "  uvirt"       ; UVIRT

; when pt_present is set:
Static PteMsgs, LABEL, WORD
        dw      dataOFFSET PtePageablemsg       ; 0: Pageable
        dw      dataOFFSET PteUvirtmsg          ; 1: UVIRT
        dw      dataOFFSET PteResidentmsg       ; 2: Resident
        dw      dataOFFSET PteUvirtmsg          ; 3: UVIRT

; pte frame interpretation strings:
Static PteFrameinvalidmsg,      STRING, "        "
Static PteFramevpidmsg,         STRING, "  vp id="
Static PteFrameframemsg,        STRING, "  frame="

endif

;
;       PTE OpInterpret format list
;

Static  PrtPTE, LABEL, BYTE
ifdef OS2
        JumpIfBitSet    0, PTE_Present, PteFrame

;       Present bit is clear; display not-present frame interpretation

        OutMsg          PteFramevpidmsg
        JumpOp          PteFrameDone
PteFrame label byte
        OutMsg          PteFrameframemsg
PteFrameDone label byte
endif
        OutBitFHexPtr   0, PTE_PageFrame, <width PTE_PageFrame>, 5

        OutBlanks       2
        OutBitFHexPtr   0, PTE_Aval, <width PTE_Aval>

        OutBlanks       4
        OutBitFHexPtr   0, PTE_Res, <width PTE_Res>

        OutBlanks       2
        OutMsgIfBitSet  0, PTE_Dirty, Dmsg      ; Dirty
        OutMsgIfBitClr  0, PTE_Dirty, cmsg      ; clean

        OutBlanks       2
        OutMsgIfBitSet  0, PTE_Accessed, Amsg   ; Accessed
        OutMsgIfBitClr  0, PTE_Accessed, uamsg  ; unaccessed

        OutBlanks       2
        OutMsgIfBitSet  0, PTE_CacheDisable, CDmsg ; Cache Disabled
        OutMsgIfBitClr  0, PTE_CacheDisable, blmsg

        OutBlank
        OutMsgIfBitSet  0, PTE_WriteThrough, WTmsg ; Write Through
        OutMsgIfBitClr  0, PTE_WriteThrough, blmsg

        OutBlank
        OutMsgIfBitSet  0, PTE_User, Umsg       ; User
        OutMsgIfBitClr  0, PTE_User, smsg       ; supervisor

        OutBlanks       2
        OutMsgIfBitSet  0, PTE_Write, Wmsg      ; Writable
        OutMsgIfBitClr  0, PTE_Write, rmsg      ; read-only

        OutBlanks       2
        OutMsgIfBitSet  0, PTE_Present, Pmsg    ; Present
        OutMsgIfBitClr  0, PTE_Present, nmsg    ; not present
ifdef OS2

        ; print state

        OutMsgBitF      0, PTE_Aval, 2, PteMsgs
endif
        OutCrLf

        EndOp


;
;       Tss OpInterpret format list
;

Static  PrtTss16, LABEL, BYTE

        OutMsglc        AXmsg
        OutWordHexPtr   tss16_ax
        OutBlanks       3

        OutMsglc        BXmsg
        OutWordHexPtr   tss16_bx
        OutBlanks       3

        OutMsglc        CXmsg
        OutWordHexPtr   tss16_cx
        OutBlanks       3

        OutMsglc        DXmsg
        OutWordHexPtr   tss16_dx
        OutBlanks       3

        OutMsglc        SPmsg
        OutWordHexPtr   tss16_sp
        OutBlanks       3

        OutMsglc        BPmsg
        OutWordHexPtr   tss16_bp
        OutBlanks       3

        OutMsglc        SImsg
        OutWordHexPtr   tss16_si
        OutBlanks       3

        OutMsglc        DImsg
        OutWordHexPtr   tss16_di
        OutCrLf

        OutMsglc        IPmsg
        OutWordHexPtr   tss16_ip
        OutBlanks       3

        OutMsglc        CSmsg
        OutWordHexPtr   tss16_cs
        OutBlanks       3

        OutMsglc        DSmsg
        OutWordHexPtr   tss16_ds
        OutBlanks       3

        OutMsglc        ESmsg
        OutWordHexPtr   tss16_es
        OutBlanks       3

        OutMsglc        SSmsg
        OutWordHexPtr   tss16_ss
        OutBlanks       3

        CallOp          PrtFlags, tss16_flags
        OutCrLf

        OutStrlc        "SS0="
        OutWordHexPtr   tss16_ss0
        OutBlanks       2

        OutStrlc        "SP0="
        OutWordHexPtr   tss16_sp0
        OutBlanks       2

        OutStrlc        "SS1="
        OutWordHexPtr   tss16_ss1
        OutBlanks       2

        OutStrlc        "SP1="
        OutWordHexPtr   tss16_sp1
        OutBlanks       2

        OutStrlc        "SS2="
        OutWordHexPtr   tss16_ss2
        OutBlanks       2

        OutStrlc        "SP2="
        OutWordHexPtr   tss16_sp2
        OutCrLf

        OutMsglc        IOPLmsg
        OutBitFHexPtr   tss16_flags, 12,  2
        OutBlanks       4

        OutMsglc        LDTRmsg
        OutWordHexPtr   tss16_ldt
        OutBlank

        OutStrlc        "LINK="
        OutWordHexPtr   tss16_backlink
        OutCrLf

        EndOp

Static  PrtTss, LABEL, BYTE

        OutMsglc        EAXmsg
        OutDwordHexPtr  tss_eax
        OutBlank

        OutMsglc        EBXmsg
        OutDwordHexPtr  tss_ebx
        OutBlank

        OutMsglc        ECXmsg
        OutDwordHexPtr  tss_ecx
        OutBlank

        OutMsglc        EDXmsg
        OutDwordHexPtr  tss_edx
        OutBlank

        OutMsglc        ESImsg
        OutDwordHexPtr  tss_esi
        OutBlank

        OutMsglc        EDImsg
        OutDwordHexPtr  tss_edi
        OutCrLf

        OutMsglc        EIPmsg
        OutDwordHexPtr  tss_eip
        OutBlank

        OutMsglc        ESPmsg
        OutDwordHexPtr  tss_esp
        OutBlank

        OutMsglc        EBPmsg
        OutDwordHexPtr  tss_ebp
        OutBlank

        OutMsglc        IOPLmsg
        OutBitFHexPtr   tss_eflags, 12,  2
        OutBlank

        CallOp          PrtRFVM, tss_eflags     ; Only RF/VM flags
        OutBlank
        CallOp          PrtFlags, tss_eflags
        OutCrLf

        OutMsglc        CSmsg
        OutWordHexPtr   tss_cs
        OutBlank

        OutMsglc        SSmsg
        OutWordHexPtr   tss_ss
        OutBlank

        OutMsglc        DSmsg
        OutWordHexPtr   tss_ds
        OutBlank

        OutMsglc        ESmsg
        OutWordHexPtr   tss_es
        OutBlank

        OutMsglc        FSmsg
        OutWordHexPtr   tss_fs
        OutBlank

        OutMsglc        GSmsg
        OutWordHexPtr   tss_gs
        OutBlanks       2

        OutMsglc        CR3msg
        OutDwordHexPtr  tss_cr3
        OutCrLf

        OutStrlc        "SS0="
        OutWordHexPtr   tss_ss0
        OutBlanks       2

        OutStrlc        "ESP0="
        OutDwordHexPtr  tss_esp0
        OutBlanks       2

        OutStrlc        "SS1="
        OutWordHexPtr   tss_ss1
        OutBlanks       2

        OutStrlc        "ESP1="
        OutDwordHexPtr  tss_esp1
        OutBlanks       2

        OutStrlc        "SS2="
        OutWordHexPtr   tss_ss2
        OutBlanks       2

        OutStrlc        "ESP2="
        OutDwordHexPtr  tss_esp2
        OutCrLf

        OutMsglc        LDTRmsg
        OutWordHexPtr   tss_ldt
        OutBlanks       2

        OutStrlc        "LINK="
        OutWordHexPtr   tss_backlink
        OutBlanks       2

        OutStrlc        "TFlags="
        OutWordHexPtr   tss_tflags
        OutBlanks       2

        OutStrlc        "I/O Map="
        OutWordHexPtr   tss_iomap
        OutCrLf

        EndOp

;
;       Dump subfunctions command table
;

Static  DumpCommands, LABEL, BYTE
        CmdTable_s <"A", codeOFFSET DumpAsciiz>
        CmdTable_s <"B", codeOFFSET DumpByte>
        CmdTable_s <"D", codeOFFSET DumpDword>
        CmdTable_s <"G", codeOFFSET DumpGDT>
        CmdTable_s <"I", codeOFFSET DumpIDT>
        CmdTable_s <"L", codeOFFSET DumpLDT>
        CmdTable_s <"P", codeOFFSET DumpPTE>
        CmdTable_s <"T", codeOFFSET DumpTSS>
        CmdTable_s <"W", codeOFFSET DumpWord>
        CmdTable_s <0,   codeOFFSET perr>

DataSegmentEnd

CodeSegmentStart

Extern  perr, NEAR

;***    Dump
;
;       Dump memory in both hex and ASCII or tables.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL, except BP, SS.
;

DefProc Dump, NEAR, PUBLIC
        Pcall   IsSeparator             ; (AL) = letter on command line
        jz      dmp1
        push    ax
        Pcall   SkipB
        pop     ax
        jmp     short dmp2

dmp1:   mov     al,DefMode              ; (AL) = command letter
dmp2:   mov     si,dataOFFSET DumpCommands
        Pcall   ExecSubr
EndProc


;***    DumpIDT
;
;       Dump the IDT.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL, except BP, SS.
;

DefProc DumpIDT, NEAR, LOCAL

LocVar  PFlag,    BYTE
LocVar  NumEntries, WORD
LocVar  TmpAddr,    <size AddrS>
LocVar  IdtAddr,    <size AddrS>
LocVar  DescEntry,  <size Desc>

BeginProc
        mov     PFlag,0                 ; default all flag
        Pcall   PeekChr
        cmp     al,"A"
        jne     short pdt10
        Pcall   SkipB
        or      PFlag,DDT_ALL

pdt10:  mov     NumEntries,8192         ; assume 64K IDT limit
        mov     cx,_sizeIDT
        jcxz    short pdt20             ; jump if 64K limit
        shr     cx,3                    ; divide by size of descriptor
        mov     NumEntries,cx           ; default number of descriptor entries

pdt20:  xor     dx,dx                   ; default starting entry
        Pcall   ScanP                   ; check if any more arguments

;bug  bx was getting garbage value
        lea     bx,TmpAddr              ; bx needs to be initialized    DJ
        jz      short pdt60

;       lea     bx,TmpAddr              ; moving this above             DJ
        Pcall   FillDataAddr, <bx, dx, 0>
        Pcall   EvalRange, <bx, bx, 1>
        mov     dx,[bx].AddrOff.LowWord

        cmp     cx,1
        jne     short pdt30
        or      PFlag,DDT_ALL           ; print all if one selector is printed

pdt30:  cmp     dx,NumEntries           ; check if passed end of table
        jb      short pdt40
        lea     bx,TmpAddr
        mov     ax,DEBERR_INVALID_SELECTOR
        Pcall   PrintMemErr         ; display the error message
        Pcall   crlf
        jmp     pdt90               ; error, leave

pdt40:  sub     NumEntries,dx           ; (NumEntries) = number of bytes left
        cmp     cx,NumEntries
        jbe     short pdt60
        mov     cx,NumEntries           ; if above table length use table len


;       Begining of descriptor table print loop
;       (BX) = AddrS of table to print
;       (DX) = starting entry number
;       (CX) = number of entries to print

        jcxz    short pdt90

pdt60:  push    cx
        mov     si,dx                   ; (SI) = starting entry number
        shl     si,3                    ; (SI) = starting offset into table
        lea     di,DescEntry
        mov     cx,(size Desc)
        mov     es,_ptrIDT+2
@@:     mov     al,es:[si]
        mov     [di],al
        inc     si
        inc     di                      ; get descriptor into local buffer
        loop    @B
        mov     ax,ds
        mov     es,ax                   ; restore ES
        pop     cx

        test    PFlag,DDT_ALL
        jnz     short pdt70

        test    DescEntry.DescAccess,not (D_PRES + D_PRIV)
        jz      short pdt80

pdt70:  lea     di,DescEntry
        cmp     dx,NUMBER_TRAPS         ; Is this a trap vector we care about?
        jae     short pdt78             ;  no, just dump it
        push    bx
        Pcall   GetTrapTblEntry, <dx>   ; (BX) = trap table entry
        test    [bx].TrapTblFlag,TRAP_PM_TEMP ; Do we hook it temporarily?
        jz      short pdt75             ;  no, just dump it
        test    [bx].TrapTblFlag,TRAP_PM_HARD ; Do we have a "hard" hook?
        jnz     short pdt75             ;  yes, show it
        lea     di,[bx].TrapTblPMsave   ; Dump the "real" descriptor
pdt75:  pop     bx
pdt78:  Pcall   PrintDesc               ; Print the descriptor
        Pcall   checkchr                ; check for stop key

pdt80:  Pcall   AddAddr, <size Desc, 0>
        inc     dx
        loop    short pdt60
pdt90:
EndProc


;***    DumpGDT
;
;       Dump the GDT.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL, except BP, SS.
;

DefProc DumpGDT, NEAR, LOCAL
        Pcall   DumpDescTable, <0>
EndProc


;***    DumpLDT
;
;       Dump the current LDT
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL, except BP, SS.
;

DefProc DumpLDT, NEAR, LOCAL
        mov     dx,DDT_LDT
        Pcall   PeekChr                 ; (AL) = option character
        jz      dlt40

        cmp     al,"P"                  ; check for print private option
        jnz     short dlt10
        or      dx,DDT_NOSHARED         ; if so, turn off shared
        jmp     short dlt30

dlt10:  cmp     al,"S"                  ; check for print shared option
        jnz     short dlt20
        or      dx,DDT_NOPRIVATE        ; if so, turn off private
        jmp     short dlt30

dlt20:  cmp     al,"H"                  ; check for print huge option
        jnz     short dlt40
        or      dx,DDT_HUGE             ; if so, turn on huge

dlt30:  Pcall   SkipB
dlt40:  Pcall   DumpDescTable, <dx>
EndProc


;***    DumpPTE
;
;       Dump the current page tables
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL, except BP, SS.
;

DefProc DumpPTE, NEAR, LOCAL

LocVar  dpt_pde, DWORD
LocVar  dpt_pdephy, DWORD
LocVar  dpt_pte, DWORD
LocVar  dpt_ptephy, DWORD
LocVar  dpt_Flags, WORD
LocVar  dpt_TmpAddr, <size AddrS>
LocVar  dpt_Count, DWORD
LocVar  dpt_cline, WORD

BeginProc
.386p
dpt00:  xor     cx,cx
dpt05:  Pcall   PeekChr                 ; (AL) = option character
        jz      short dpt20

        test    cx,DP_NOPTE             ; check for verbose option
        jnz     dpt10
        cmp     al,"D"
        jnz     short dpt10
        or      cx,DP_NOPTE
        jmp     short dpt15

dpt10:  test    cx,DP_ALL               ; check for all option
        jnz     dpt20
        cmp     al,"A"
        jnz     short dpt20
        or      cx,DP_ALL

dpt15:  Pcall   SkipB                   ; skip the input character
        jmp     short dpt05

;       (CX) = dump flags

dpt20:  or      cx,DP_PDE               ; always dump first PDE
        mov     [dpt_Flags],cx

        lea     bx,[dpt_TmpAddr]        ; set default start address to 0
        Pcall   FillDataAddr, <bx, 0, 0>

        mov     ecx,-1                  ; default pte count is all
        Pcall   ScanP                   ; check if any more arguments
        jz      short dpt40             ; jmp if none

        Pcall   EvalRange, <bx, bx, 16> ; default to 16 (64k worth) of ptes
        movzx   ecx,cx
        jc      short dpt30             ; jmp if (ECX) contains a byte count

        test    [dpt_Flags],DP_NOPTE    ; if dumping PDEs only
        jz      dpt40
        shl     ecx,LinPageDir - LinPageTable ; convert PDE count to PTE count
        jmp     short dpt40

dpt30:  add     ecx,(1 shl LinPageTable) - 1 ; convert byte count to PTE count
        shr     ecx,LinPageTable

;       (BX) = &[dpt_TmpAddr]
;       (ECX) = number of page table entries to dump

dpt40:  mov     [dpt_Count],ecx
        mov     cx,1
        Pcall   AddrToLin       ; (ax:dx)=laddr = AddrToLin(bx=&tmpaddr,cx=len)
        jc      dpte
        Pcall   FillLinAddr, <bx, dx, ax>
        shl     eax,16
        mov     ax,dx                   ; (EAX) = linear address

        mov     [dpt_cline],0
dpt50:  push    eax
        push    ecx
        push    edx
        Pcall   checkchr                ; check for stop character
        pop     edx
        pop     ecx
        pop     eax

        mov     [dpt_pdephy],-1         ; no pde physical address yet
        mov     [dpt_ptephy],-1         ; no pte physical address yet
        mov     [dpt_pte],0             ; no pte (pde not present)

;       (ECX)=pde, (EDX)=pde phy = GetPDE(EAX=laddr, BX=task#)

        xor     bx,bx                   ; (BX) = current task number
        push    eax
        Pcall   GetPDE
        pop     eax                     ; (EAX) = linear address
        mov     [dpt_pde],ecx
        jc      short dpt52
        mov     [dpt_pdephy],edx

;       (ECX)=pte, (EDX)=pte phy = GetPTE(EAX=laddr, EDX=pde phy, BX=task#)

        xor     bx,bx                   ; (BX) = current task number
        Pcall   GetPTE
        mov     [dpt_pte],ecx
        jc      short dpt52
        mov     [dpt_ptephy],edx

dpt52:  test    [dpt_Flags],DP_PDE
        jz      short dpt60             ; jmp if we've already dumped this PDE
        and     [dpt_Flags],not DP_PDE
        test    [dpt_Flags],DP_ALL
        jnz     short dpt55             ; jmp if dumping 0'd PDEs
        cmp     [dpt_pde],0
        je      short dpt60             ; else skip 0'd PDEs

;       Dump one PDE

dpt55:  lea     di,[dpt_pdephy]
        mov     cl,"*"
        call    PteHeaderLinFrame       ; display header, lin addr and frame
        lea     di,[dpt_pde]
        mov     si,dataOFFSET PrtPTE
        Pcall   OpInterpret

dpt60:  test    [dpt_Flags],DP_NOPTE
        jnz     short dpt90             ; jmp if skipping PTEs
        cmp     [dpt_pdephy],-1
        je      short dpt90             ; jmp if PDE is not present
        test    [dpt_Flags],DP_ALL
        jnz     short dpt65             ; jmp if dumping 0'd PTEs
        cmp     [dpt_pte],0             ; else skip 0'd PTEs
        jz      short dpt70             ; jmp if PTE is 0

;       Dump one PTE

dpt65:  lea     di,[dpt_ptephy]
        mov     cl," "
        call    PteHeaderLinFrame       ; display header, lin addr and frame
        lea     di,[dpt_pte]
        mov     si,dataOFFSET PrtPTE
        Pcall   OpInterpret

dpt70:  lea     bx,[dpt_TmpAddr]        ; bump the linear address
        Pcall   AddAddr, <<1 shl LinPageTable>, 0>
        mov     eax,[dpt_TmpAddr].AddrOff ; (EAX) = next linear address
        cmp     eax,1 shl LinPageTable
        jb      short dptxj
        test    eax,mask LinPageTable
        jnz     short dpt85
        or      [dpt_Flags],DP_PDE
dpt85:  dec     [dpt_Count]             ; are we done?
        jnz     dpt50
dptxj:  jmp     short dptx

;       Skip to next PDE

dpt90:  mov     eax,[dpt_TmpAddr].AddrOff ; (EBX) = (EAX) = linear address
        mov     ebx,eax

        and     ebx,mask LinPageTable
        shr     ebx,LinPageTable
        neg     ebx
        add     ebx,1 shl (LinPageDir - LinPageTable)
        sub     [dpt_Count],ebx         ; decrement by PTEs left in this PDE
        jbe     short dptx

        and     eax,mask LinPageDir     ; bump address to next PDE
        add     eax,1 shl LinPageDir
        jz      short dptx              ; oops, ran off the end
        mov     [dpt_TmpAddr].AddrOff,eax
        or      [dpt_Flags],DP_PDE      ; set flag to dump this PDE
        jmp     dpt50

dpte:   lea     bx,[dpt_TmpAddr]
        Jump    ErrBreak

dptx:
.286p
EndProc


;***    PteHeaderLinFrame - Display pte/pde header, linear address and frame
;
;       ENTRY   (BP) = DumpPTE's local variable stack frame
;               (DI) = pointer to frame value to display
;               (CL) = character to display after linear address
;       EXIT    NONE
;       USES    EAX, EDX, Flags

DefProc PteHeaderLinFrame, NEAR, LOCAL
        push    ds
        pop     es              ; make sure ES points to our data segment
        cmp     [dpt_cline],0
        jnz     short phl20
;        putstr <" linaddr   frame   pteframe  state res Dc Au CD WT Us rW Pn">
        mov     dx,offset str3
        Pcall   rprbuf
ifdef OS2
        mov     dx,offset str4
        Pcall   rprbuf
;        putstr  <" state">
endif
        Pcall   crlf
        mov     [dpt_cline],LINES_PER_PAGE
phl20:  dec     [dpt_cline]
.386p
        push    cx          ; save trailing character
        mov     al,'%'
        Pcall   put_ch
        mov     eax,[dpt_TmpAddr].AddrOff
        Pcall   OutRadix, <eax, 16, 8, "0">
;        printf  <"%%%08lx%c ">,<eax,cx>
        pop     ax
        Pcall   put_ch
        mov     al," "
        Pcall   put_ch

        mov     edx,dword ptr [di]
        cmp     edx,-1
        jz      short phl40
        ror     edx,PhyPageFrame
        Pcall   OutRadix, <edx, 16, 5, "0">
;        printf  <"%05lx">,<edx>
.286p
        jmp     short phlx

phl40:  mov     dx,offset str5
        Pcall   rprbuf
; putstr  <"     ">
phlx:
EndProc


;***    DumpTSS
;
;       Dump the current TSS
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL, except BP, SS.
;

DefProc DumpTSS, NEAR, LOCAL

LocVar  TmpAddr, <size AddrS>

BeginProc
        lea     bx,TmpAddr
        Pcall   FillSelAddr, <bx, RegSA.TRsav, 0, 0>
        Pcall   ScanP                   ; anything on the command line?
        jnz     short dts30             ; jump if something on command line

        lea     bx,TmpAddr
        Pcall   GetAddrInfo             ; (BL) = access byte
        jc      short dts20

        test    bl,D_32
        jz      short dts40             ; jump if 16 bit TSS

dts10:  mov     dx,(size tss_s)         ; do 32 TSS
        lea     bx,TmpAddr
        Pcall   GetCache                ; (DI) = cache buffer
        jc      short dts20
        mov     si,dataOFFSET PrtTss
        Pcall   OpInterpret
        lea     bx,TmpAddr
        Pcall   DumpIOPM
        jmp     short dtsx

dts20:  Jump    ErrBreak

;       (BX) = &TmpAddr

dts30:  Pcall   EvalAddr, <bx, bx>      ; evaluate command line address
        Pcall   CheckAddr, <bx>
        test    DebData.InitFlag,INIT_ENV386
        jnz     short dts10             ; jump if 32 bit TSS

dts40:  mov     dx,(size tss16_s)
        lea     bx,TmpAddr
        Pcall   GetCache                ; (DI) = cache buffer
        jc      short dts20
        mov     si,dataOFFSET PrtTss16
        Pcall   OpInterpret
dtsx:
EndProc


;***    DumpIOPM
;
;       Dump the current 32 bit TSS's IOPM
;
;       ENTRY:  (BX) = pointer to 32 TSS
;
;       EXIT:   NONE
;
;       USES:   AX, BX, CX, DX, SI, DI, Flags
;
;       NOTE:   This code assumes the tss printed finished
;               with a CR, LF.
;

DefProc DumpIOPM, NEAR, LOCAL

LocVar  dip_fState,WORD
LocVar  dip_bTss,BYTE

BeginProc
        Pcall   GetWordOff, <tss_iomap, 0>      ; (DX) = iopm offset
        jc      short dipe                      ; jump if error
        Pcall   AddAddr, <dx, 0>
        xor     si,si
        xor     di,di
        mov     [dip_fState],0                  ; initial state, 0 (no trap)

;       (dip_bTss) = byte from tss
;       (dip_fState) = state (0 = no trap, 1 = trap)
;       (BX) = TSS AddrS
;       (CX) = bit count for TSS byte
;       (SI) = last state change's port number
;       (DI) = current port number

dip10:  Pcall   checkchr                        ; check for stop character
        Pcall   GetByte                         ; (AL) = iopm byte
        jc      short dip50                     ; jump if error
        mov     cx,8
        mov     [dip_bTss],al

;       Start of inner per tss byte loop

dip20:  xor     dx,dx
        shr     [dip_bTss],1                    ; (CY) = bit
        rcl     dx,1                            ; (DX) = carry flag
        cmp     [dip_fState],dx                 ; did the state change?
        je      short dip40                     ;  no, keep going
        mov     [dip_fState],dx                 ; set new state
        or      dx,dx
        jnz     short dip30                     ; jump if changed from 0 to 1
        Pcall   PrintPorts
dip30:  mov     si,di                           ; (SI) = last port number
dip40:  inc     di                              ; (DI) = next port number
        jz      short dip60                     ; exit if > 64K ports
        loop    short dip20

        Pcall   AddAddr, <1, 0>
        jmp     short dip10

dip50:  cmp     ax,DEBERR_OFFSET_PAST_LIMIT
        jne     short dipe                      ; jump if not limit error
        cmp     [dip_fState],0
        jne     short dip55                     ; jump if state == no trap
        mov     si,di
dip55:  xor     di,di                           ; (DI) = last port
        jmp     short dip70

dip60:  cmp     [dip_fState],0
        je      short dip80                     ; jump if state == no trap
dip70:  Pcall   PrintPorts
dip80:  Pcall   CrLfColOne
        Pcall   crlf
EndProc
dipe:   Jump    ErrBreak

;***    PrintPorts
;
;       Print a range of trapped ports.
;
;       ENTRY:  (SI) = starting port
;               (DI) = ending port
;
;       EXIT:   NONE
;
;       USES:   AX, DX, Flags
;

DefProc PrintPorts, NEAR, LOCAL
        mov     al,[CursorColumn]       ; (AX) = current cursor column
        cmp     al,70                   ; is it going to wraping?
        jb      short prp10             ;  no, skip CR/LF
        Pcall   crlf                    ;  yes, print CR/LF, skip ","
        jmp     short prp30

prp10:  or      al,al                   ; is this the first thing printed?
        jnz     short prp20             ;  no, print comma
        putstr  "ports trapped: "       ;  yes, print header
        jmp     short prp30

prp20:  mov     al,","                  ; print a comma to separate the ports
        Pcall   put_ch

prp30:  xor     ax,ax
        mov     dx,si
        Pcall   OutHex

        mov     dx,di                   ; (DX) = current port
        dec     dx                      ; (DX) = last port of same state
        cmp     si,dx                   ; is there only one port?
        je      short prpx              ;  yes, don't print second

        mov     al,"-"
        Pcall   put_ch
        xor     ax,ax
        Pcall   OutHex
prpx:
EndProc

;***    DumpByte
;
;       Dump the memory in hex byte and ascii format.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL, except BP, SS.
;

DefProc DumpByte, NEAR, LOCAL
        mov     bx,dataOFFSET DumpAddr
        Pcall   EvalRange, <bx, bx, 128>
        Pcall   CheckAddr, <bx>
        mov     DefMode,"B"
        jcxz    short ddb5
        mov     dx,cx

;       (DX) = number of bytes to print

ddb1:   Pcall   OutAddrS, <bx>
        test    DebData.InitFlag,INIT_ENV386
        jnz     ddb2
        Pcall   blank
ddb2:   mov     si,16                   ; (SI) = number of bytes on a line
        cmp     dx,si
        jae     short ddb3
        mov     si,dx                   ; (SI) = all the bytes to print

ddb3:   mov     cx,si
        Pcall   PrtHexRow               ; show it in hex, (DI) = num printed

;       Compute tab length. ASCII dump always appears on right side
;       screen regardless of how many bytes were dumped. Figure 3
;       characters for each byte dumped and subtract from 50/49, which
;       allows a minimum of 2/1 blanks after the last byte dumped.

        imul    di,di,3                 ; (DI) = (number printed) * 3
        test    DebData.InitFlag,INIT_ENV386
        mov     cx,49
        jnz     ddb4
        mov     cx,50
ddb4:   sub     cx,di                   ; amount to tab in CX
        Pcall   tab

        mov     cx,si
        Pcall   PrtAsciiRow             ; show it in ASCII
        Pcall   crlf
        Pcall   checkchr                ; check for stop character
        sub     dx,si                   ; loop until count is zero
        jnz     short ddb1              ;
ddb5:
EndProc

;***    PrtHexRow
;
;       ENTRY:  (CX) = number of bytes to print
;               (BX) = AddrS pointer
;
;       EXIT:   (CX) = number of bytes left to print
;               (DI) = number of bytes printed
;
;       USES:   AX, CX, DI, Flags
;

DefProc PrtHexRow, NEAR, LOCAL
        xor     di,di
phr1:   Pcall   GetByteOff, <di, 0>
        jc      short phrx
        inc     di
        cmp     di,9
        je      short phr2
        Pcall   blank                   ; space between bytes
        jmp     short phr3

phr2:   push    ax
        mov     al,"-"                  ; mark every 8 bytes
        Pcall   put_ch
        pop     ax
phr3:   Pcall   hex                     ; display  byte
        loop    short phr1
phrx:
EndProc

;***    PrtAsciiRow
;
;       Prints a row of ascii characters
;
;       ENTRY:  (CX) = number of bytes to print
;               (BX) = AddrS pointer
;
;       EXIT:   NONE
;
;       USES:   AX, CX, Flags
;

DefProc PrtAsciiRow, NEAR, LOCAL
par1:   Pcall   GetByte                 ; (AL) = byte from memory
        jnc     short par2
        Jump    ErrBreak

par2:   Pcall   AddAddr, <1, 0>
        and     al,7fh                  ; ASCII uses 7 bits
        cmp     al,7fh                  ; don't try to print RUBOUT
        jz      short par3
        cmp     al," "                  ; check for control characters
        jnc     short par4
par3:   mov     al,"."                  ; if unprintable character
par4:   Pcall   put_ch                 ; print ASCII character
        loop    short par1              ; CX times
EndProc

;***    DumpAsciiz
;
;       Dump the memory in asciiz format.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL, except BP, SS.
;

DefProc DumpAsciiz, NEAR, LOCAL
        mov     bx,dataOFFSET DumpAddr
        Pcall   EvalRange, <bx, bx, 128>
        Pcall   CheckAddr, <bx>
        mov     DefMode,"A"
        Pcall   OutAddrS, <bx>
        Pcall   blank
        xor     di,di
        jmp     short dda1
dda0:   Pcall   put_ch
dda1:   Pcall   GetByteOff, <di, 0>
        jc      short dda2
        inc     di
        or      al,al
        loopnz  dda0
dda2:   Pcall   crlf
EndProc

;***    DumpWord
;
;       Dump the memory in word hex format.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL except BP, SS.
;

DefProc DumpWord, NEAR, LOCAL

LocVar  NumObjects, WORD                ; total num of objects to print
LocVar  NumPerLine, WORD                ; current num of objects on line

BeginProc
        mov     bx,dataOFFSET DumpAddr
        Pcall   EvalRange, <bx, bx, 64>
        mov     DefMode,"W"
        jcxz    dwdx
        jnc     dwd0                    ; jump if range is in objects

        dec     cx                      ; convert bytes to objects
        shr     cx,1                    ;
        inc     cx                      ;

dwd0:   mov     NumObjects,cx           ; save number of objects
        Pcall   CheckAddr, <bx>

dwd1:   mov     NumPerLine,0
        Pcall   OutAddrS, <bx>
        Pcall   blank
        Pcall   blank

;       Print row of hex words

dwd2:   Pcall   GetWord                 ; (DX) = word
        jc      dwd3
        mov     ax,dx
        Pcall   out16                   ; and display it
        Pcall   blank
        Pcall   AddAddr, <2, 0>
        dec     NumObjects              ; check if all the objects
        jz      dwd4                    ;  have been printed.
        inc     NumPerLine              ; break when 8 words have
        cmp     NumPerLine,8            ;  been printed.
        jb      dwd2
        Pcall   crlf
        Pcall   checkchr            ; check for stop character
        jmp     short dwd1

dwd3:   Jump    ErrBreak

dwd4:   Pcall   crlf
dwdx:
EndProc

;**     DumpDword
;
;       Dump the memory in dword hex format.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   ALL except BP, SS.
;

DefProc DumpDword, NEAR, LOCAL

LocVar  NumObjects, WORD                ; total num of objects to print
LocVar  NumPerLine, WORD                ; current num of objects on line

BeginProc
        mov     bx,dataOFFSET DumpAddr
        Pcall   EvalRange, <bx, bx, 32>
        mov     DefMode,"D"
        jcxz    ddwx
        jnc     ddw10                   ; jump if range is in objects

        dec     cx                      ; convert to number of objects
        shr     cx,2                    ;
        inc     cx                      ;

ddw10:  mov     NumObjects,cx           ; save number of objects
        Pcall   CheckAddr, <bx>

ddw20:  mov     NumPerLine,0
        Pcall   OutAddrS, <bx>
        Pcall   blank
        Pcall   blank

;       Print row of hex double words

ddw30:  Pcall   GetDword                ; (AX:DX) = dword
        jc      ddw60
        test    DebData.InitFlag,INIT_ENV386
        jnz     short ddw40             ; jump if 32 bit mode
        Pcall   OutColonDword, <dx, ax> ; print word:word
        jmp     short ddw50

ddw40:  Pcall   Out32                   ; print just a dword
ddw50:  Pcall   blank
        Pcall   AddAddr, <4, 0>
        dec     NumObjects              ; check if all the objects
        jz      short ddw70             ;  have been printed.
        inc     NumPerLine              ; break when 4 dwords have
        cmp     NumPerLine,4            ;  been printed.
        jb      ddw30
        Pcall   crlf
        Pcall   checkchr                ; check for stop character
        jmp     short ddw20

ddw60:  Jump    ErrBreak

ddw70:  Pcall   crlf
ddwx:
EndProc


;***    DumpDescTable - dump descriptor table
;
;       Pcall   DumpDescTable, <StartEntry>
;
;       Dumps a descriptor table in a readable format
;       We print the table one entry per line, with the line
;       indicating what the descriptor is, and all the important data.
;
;       ENTRY:  (StartEntry) = start of LDT or GDT table entry.
;
;       EXIT:   NONE
;
;       USES:   AX, BX, CX, DX, DI, ES, Flags
;

DefProc DumpDescTable, NEAR, LOCAL

ArgVar  StartEntry, WORD
LocVar  EndEntry,   WORD
LocVar  NumEntries, WORD
LocVar  PFlags,     BYTE
LocVar  DescAddr,   <size AddrS>
LocVar  DescEntry,  <size Desc>

BeginProc
        mov     ax,StartEntry
        and     StartEntry,TABLE_MASK
        .errnz  (DDT_LDT - TABLE_MASK)
        mov     PFlags,al
        mov     NumEntries,0ffffh       ; default = all the entries in the table
        Pcall   PeekChr
        cmp     al,"A"                  ; check for print all option
        jne     short ddt1
        Pcall   SkipB
        or      PFlags,DDT_ALL

ddt1:   Pcall   ScanP
        jz      ddt10                   ; jump if empty command line

        lea     bx,DescAddr
        Pcall   FillDataAddr, <bx, StartEntry, 0>
        Pcall   EvalRange, <bx, bx, 1>
        mov     dx,[bx].AddrOff.LowWord
        jnc     ddt2                    ; jump if number of objects
        shr     cx,3                    ; divide by 8 (size Desc)
        inc     cx                      ; round up

ddt2:   mov     NumEntries,cx           ; (CX) = ending selector entry
        mov     ax,StartEntry           ; (AX) = old starting entry
        mov     StartEntry,dx           ; (DX) = starting selector entry

        test    al,TABLE_MASK
        jz      ddt3                    ; jump if original start is GDT

        test    dl,TABLE_MASK
        jnz     ddt10                   ; jump if new and original is LDT

        putstr  <"GDT", CR, LF>         ; using "DL" command to display GDT sel
        and     PFlags,not (DDT_NOPRIVATE+DDT_NOSHARED+DDT_HUGE)
        jmp     short ddt10

ddt3:   test    dl,TABLE_MASK
        jz      ddt10                   ; jump if new and original start is GDT
        putstr  <"LDT", CR, LF>         ; using "DG" command to display LDT sel

ddt10:  mov     EndEntry,-1             ; start with 64k GDT or LDT limit
        lea     bx,DescAddr             ;  yes, get GDT address
        mov     cx,_sizeGDT
        test    StartEntry,TABLE_MASK   ; LDT or GDT?
        jz      ddt20
        mov     cx,_sizeLDT

ddt20:  and     cl,SEL_LOW_MASK         ; round down
        jcxz    ddt25                   ; jump if 64K limit
        mov     EndEntry,cx             ; save end of table

ddt25:  mov     ax,StartEntry           ; (AX) = starting entry offset
        and     al,SEL_LOW_MASK         ; make sure it's on desc boundary
        Pcall   AddAddr, <ax, 0>

        mov     cx,NumEntries           ; (CX) = number of entries to print
        cmp     cx,1                    ; if equal only one entry is printed
        jne     ddt30
        mov     PFlags,DDT_ALL          ; print all if one selector is printed

ddt30:  cmp     ax,EndEntry             ; check if passed end of table
        jb      ddt35
        lea     bx,DescAddr
        Pcall   FillDataAddr, <bx, ax, 0>
        mov     ax,DEBERR_INVALID_SELECTOR
        Pcall   PrintMemErr         ; display the error message
        Pcall   crlf
        jmp     ddtx                ; error, leave

ddt35:  mov     dx,StartEntry

;       Begining of descriptor table print loop
;       (AX) = starting entry offset
;       (BX) = AddrS of table to print
;       (DX) = starting entry to be displayed (selector)
;       (CX) = number of entries to print

        jcxz    ddt45                   ; jump if no entries to be displayed

ddt40:  mov     ax,dx
        and     al,SEL_LOW_MASK         ; mask off low 3 bits
        cmp     ax,EndEntry             ; if past end of table
        jb      @F
ddt45:  jmp     ddtx                    ; time to stop dumping

@@:     SaveReg <ax, cx, si>
        lea     di,DescEntry
        mov     es,_ptrGDT+2
        test    dx,TABLE_MASK           ; GDT or LDT?
        jz      @F
        mov     es,_ptrLDT+2            ; in the LDT
@@:     mov     si,dx                   ; get the starting offset
        and     si,0fff8h               ; get rid of junk bits
        mov     cx,(size Desc)
@@:     mov     al,es:[si]
        mov     [di],al                 ; copy the descriptor
        inc     si
        inc     di
        loop    @B
        mov     ax,ds
        mov     es,ax                   ; restore ES
        RestReg <si, cx, ax>

        test    PFlags,DDT_ALL+DDT_HUGE
        jnz     ddt55
        test    DescEntry.DescAccess,not (D_PRES + D_PRIV)
        jz      ddt90

ddt55:  cmp     NumEntries,1            ; if only one entry being displayed
        je      ddt70
        and     dl,RPL_CLR              ; clear RPL bits
        mov     al,DescEntry.DescAccess
        test    al,not (D_PRES + D_PRIV)
        jz      ddt60
        shr     al,DAC_DPL
        and     al,RPL_MASK             ; clear everything except the RPL bits
        or      dl,al                   ; make RPL = DPL of descriptor
        jmp     short ddt70

ddt60:  test    dl,TABLE_MASK
        jz      ddt70
        or      dl,RPL_MASK             ; make RPL = 3 if LDT descriptor

ddt70:  test    dl,TABLE_MASK
        jz      ddt80
        mov     al,PFlags
        test    al,DDT_NOPRIVATE
        jz      ddt75
        test    dl,SHARE_MASK
        jnz     ddt80                   ; jmp if shared, print it
        jmp     short ddt90             ; jmp if private, don't print it

ddt75:  test    al,DDT_NOSHARED
        jz      ddt80
        test    dl,SHARE_MASK
        jnz     ddt90                   ; jmp if shared, don't print it

ddt80:  lea     di,DescEntry
        Pcall   PrintDesc
        Pcall   checkchr                ; check for stop key
ddt90:  mov     ax,size Desc
        test    PFlags,DDT_HUGE
        jz      ddt95
        mov     ax,HUGEINCR
ddt95:  Pcall   AddAddr, <ax, 0>
        add     dx,ax                   ; this add won't affect the 1st 3 bits
        jc      ddtx
        loop    ddt100
        jmp     ddtx

ddt100: jmp     ddt40
ddtx:
EndProc


;***    PrintDesc
;
;       Prints a descriptor number and entry.
;
;       ENTRY:  (DI) = descriptor entry
;               (DX) = selector/entry number
;               (BX) = AddrS of descriptor to print
;
;       EXIT:   NONE
;
;       USES:   AX, SI, Flags
;

DefProc PrintDesc, NEAR, LOCAL
        SaveReg <bx, cx, dx, di>
        Pcall   out16
        Pcall   blank
        Pcall   blank
        mov     si,dataOFFSET PrtDesc
        Pcall   OpInterpret
        Pcall   crlf
        RestReg <di, dx, cx, bx>
EndProc

CodeSegmentEnd

        end
