;       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

LINES_PER_PAGE		equ	23

DataSegmentStart

TERSE = 1

Extern DebData,		WORD
Extern RegSA,		WORD
Extern DefMode,		BYTE
Extern DumpAddr,	WORD
Extern LoadAllSav,	WORD
Extern LoadallSaved,	BYTE
Extern CursorColumn,	BYTE

;
; 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
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 "

;
;	Loadall buffer OpInterpret format list
;

Static	PrtLoadall, LABEL, BYTE
	OutMsglc	AXmsg
	OutWordHexPtr	loadall_AX
	OutBlanks	2

	OutMsglc	BXmsg
	OutWordHexPtr	loadall_BX
	OutBlanks	2

	OutMsglc	CXmsg
	OutWordHexPtr	loadall_CX
	OutBlanks	2

	OutMsglc	DXmsg
	OutWordHexPtr	loadall_DX
	OutBlanks	2

	OutMsglc	SPmsg
	OutWordHexPtr	loadall_SP
	OutBlanks	2

	OutMsglc	BPmsg
	OutWordHexPtr	loadall_BP
	OutBlanks	2

	OutMsglc	SImsg
	OutWordHexPtr	loadall_SI
	OutBlanks	2

	OutMsglc	DImsg
	OutWordHexPtr	loadall_DI
	OutCrLf

	OutMsglc	IPmsg
	OutWordHexPtr	loadall_IP
	OutBlanks	2

	OutMsglc	CSmsg
	OutWordHexPtr	loadall_CS
	OutBlanks	2

	OutMsglc	DSmsg
	OutWordHexPtr	loadall_DS
	OutBlanks	2

	OutMsglc	ESmsg
	OutWordHexPtr	loadall_ES
	OutBlanks	2

	OutMsglc	SSmsg
	OutWordHexPtr	loadall_SS
	OutBlanks	2

	CallOp		PrtFlags, loadall_FLAGS
	OutCrLf

	OutMsglc	GDTRmsg
	Out24HexPtr	loadall_GDTR.CacheBaseLow
	OutBlank
	OutWordHexPtr	loadall_GDTR.CacheLimit
	OutBlanks	2

	OutMsglc	IDTRmsg
	Out24HexPtr	loadall_IDTR.CacheBaseLow
	OutBlank
	OutWordHexPtr	loadall_IDTR.CacheLimit
	OutBlanks	2

	OutMsglc	TRmsg
	OutWordHexPtr	loadall_TR
	OutBlanks	2

	OutMsglc	LDTRmsg
	OutWordHexPtr	loadall_LDTR
	OutBlank

	OutMsglc	IOPLmsg
	OutBitFHexPtr	loadall_FLAGS, 12, 2
	OutBlank

	CallOp		PrtMSW, loadall_MSW
	OutCrLf

	OutStrlc	"CSBASE="
	Out24HexPtr	loadall_CScache.CacheBaseLow
	OutBlanks	3
	OutStrlc	"CSLIM="
	OutWordHexPtr	loadall_CScache.CacheLimit
	OutBlanks	3
	OutStrlc	"CSAR="
	OutByteHexPtr	loadall_CScache.CacheAccess
	OutBlanks	3

	OutStrlc	"DSBASE="
	Out24HexPtr	loadall_DScache.CacheBaseLow
	OutBlanks	3
	OutStrlc	"DSLIM="
	OutWordHexPtr	loadall_DScache.CacheLimit
	OutBlanks	3
	OutStrlc	"DSAR="
	OutByteHexPtr	loadall_DScache.CacheAccess
	OutCrLf

	OutStrlc	"ESBASE="
	Out24HexPtr	loadall_EScache.CacheBaseLow
	OutBlanks	3
	OutStrlc	"ESLIM="
	OutWordHexPtr	loadall_EScache.CacheLimit
	OutBlanks	3
	OutStrlc	"ESAR="
	OutByteHexPtr	loadall_EScache.CacheAccess
	OutBlanks	3

	OutStrlc	"SSBASE="
	Out24HexPtr	loadall_SScache.CacheBaseLow
	OutBlanks	3
	OutStrlc	"SSLIM="
	OutWordHexPtr	loadall_SScache.CacheLimit
	OutBlanks	3
	OutStrlc	"SSAR="
	OutByteHexPtr	loadall_SScache.CacheAccess
	OutCrLf

	OutStrlc	"TRBASE="
	Out24HexPtr	loadall_TRcache.CacheBaseLow
	OutBlanks	3
	OutStrlc	"TRLIM="
	OutWordHexPtr	loadall_TRcache.CacheLimit
	OutBlanks	3
	OutStrlc	"TRAR="
	OutByteHexPtr	loadall_TRcache.CacheAccess
	OutBlanks	3

	OutStrlc	"LDTBASE="
	Out24HexPtr	loadall_LDTcache.CacheBaseLow
	OutBlanks	2
	OutStrlc	"LDTLIM="
	OutWordHexPtr	loadall_LDTcache.CacheLimit
	OutBlanks	2
	OutStrlc	"LDTAR="
	OutByteHexPtr	loadall_LDTcache.CacheAccess
	OutCrLf

	EndOp


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 <"X", codeOFFSET DumpLoadall>
	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


;***	DumpLoadall
;
;	Dump the loadall buffer
;
;	ENTRY:	NONE
;
;	EXIT:	NONE
;
;	USES:	ALL, except BP, SS.
;

DefProc	DumpLoadall, NEAR, LOCAL

LocVar	TmpAddr, <size AddrS>

BeginProc
	cmp	LoadallSaved,FALSE
	je	dla2
	mov	di,dataOFFSET LoadAllSav
	jmp	short dla3

dla1:	Jump	ErrBreak

dla2:	lea	bx,TmpAddr
	Pcall	FillPhyAddr, <bx, LOADALL_ADDR, 0>
	mov	dx,(size LoadAllStruc)
	Pcall	GetCache			; (DI) = cache buffer
	jc	dla1
dla3:	mov	si,dataOFFSET PrtLoadall
	Pcall	OpInterpret
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
	lea	bx,IdtAddr
	Pcall	GetPMIDTaddr
	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
	jz	short pdt60

	lea	bx,TmpAddr
	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
pdte:	Jump	ErrBreak		; (AX) = error code, (BX) = AddrS

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

pdt50:	mov	ax,dx			; (AX) = starting entry number
	imul	ax,size Desc		; (AX) = starting offset into table
	lea	bx,IdtAddr
	Pcall	AddAddr, <ax, 0>	; make address of table point to start

;	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
	lea	di,DescEntry
	mov	cx,(size Desc)
	Pcall	GetBuff			; get descriptor into local buffer
	pop	cx
	jc	pdte

	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

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
	test	DebData.InitFlag,INIT_CPU386
	jnz	short dpt00
	Jump	perr
.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:	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
	cmp	[dpt_cline],0
	jnz	short phl20
	putstr <" linaddr   frame   pteframe  state res Dc Au CD WT Us rW Pn">
ifdef OS2
	putstr	<" state">
endif
	Pcall	crlf
	mov	[dpt_cline],LINES_PER_PAGE
phl20:	dec	[dpt_cline]
.386p
	mov	eax,[dpt_TmpAddr].AddrOff
	printf	<"%%%08lx%c ">,<eax,cx>
	mov	edx,dword ptr [di]
	cmp	edx,-1
	jz	short phl40
	ror	edx,PhyPageFrame
	printf	<"%05lx">,<edx>
.286p
	jmp	short phlx

phl40:	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	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
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	putchar

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	putchar
	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

	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	putchar
	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	putchar			; 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	putchar
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
	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
	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
	test	StartEntry,TABLE_MASK	; dumping the GDT?
	jz	ddt15			;  no, get LDT address
	lea	bx,DescAddr		;  yes, get GDT address
	Pcall	GetLdtAddr		; (CX) = LDT table size (0 = 64k)
	jmp	short ddt20

ddt15:	lea	bx,DescAddr
	Pcall	GetGdtAddr		; (CX) = GDT table size (0 = 64k)

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
ddte:	Jump	ErrBreak		; (AX) = error code, (BX) = AddrS

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:	SaveReg	<cx>
	lea	di,DescEntry
	mov	cx,(size Desc)
	Pcall	GetBuff			; get descriptor into local buffer
	RestReg	<cx>
	jc	ddte

	mov	ax,dx
	and	al,SEL_LOW_MASK		; mask off low 3 bits
	cmp	ax,EndEntry		; if past end of table
	jb	short ddt50
ddt45:	jmp	ddtx

ddt50:	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
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
