NT4/private/ntos/boot/bootcode/hpfs/i386/macro.inc
2020-09-30 17:12:29 +02:00

782 lines
13 KiB
PHP

; SCCSID = @(#)macro.inc 12.1 88/12/19
;** Macros
;* MASSUME - do an assume
;
; made into a macro to make screwing around during debuuing
; easier
;
; Used by the file system code; not recommended for general
; use. Will be taken out at end of project. BUGBUG
MASSUME MACRO
ASSUME CS:CODE,DS:FLAT,ES:FLAT,SS:NOTHING
ENDM
;* MENTER - Do an Enter
;
; made into a macro for better code, and to avoid problems
; when USE16 (MASM doesn't generate the override)
MENTER MACRO arg1,arg2
push ebp
mov ebp,esp
ifdif <arg1>,<0>
sub esp,arg1
endif
ENDM
;* MLEAVE - do a Leave
;
; We need to generate the segment override in USE16, since
; MASM won't do it
MLEAVE MACRO
ifndef USE32
DB 66h
endif
leave
ENDM
;* GetPathBuf - Allocates from the heap memory for the PathBuffer
;
; Enter: (eax) = size of the requested heap block (hvpb not included)
; Exit: C clear:
; (eax) = ptr to the heap block
; C set: error no more heap space
; Uses: eax, flags
GetPathBuf MACRO
SAVE <EDI, ECX>
add eax, MVPFXSIZE+3+HHSIZ ; for hvpb, rounding and header
and al, 0fch ; round it to quad-boundary
ifndef GHS_
EXTRN GHS_:near
endif
call GHS_
RESTORE <ECX, EDI>
ENDM
;* FreePathBuf - Return PathBuffer to the Heap
;
;
; Enter: (reg) = ptr to PathBuffer (that's (sizeof hvbp) after the
; heap block address)
; Exit: heap block released
; Uses: reg
FreePathBuf MACRO reg
sub reg, MVPFXSIZE ; (reg) now pts to the heap block
HeapChk reg
add dword ptr -4[reg],80000000h-4
ENDM
;* Assert - sanity checks (contolled by DEBUG switch)
;
; kind: one of OFT
;
; objs: register/word which contains address
;
; nopush: if non-blank, we don't preserve registers
IFDEF DEBUG
ASSERT MACRO kind, objs, nopush, arg1
local a
a = 0
IFNDEF A_OFT
extrn A_OFT:near,A_SECPTR:near,A_DIRBLK:near,A_FNODE:near
extrn A_AS:near,A_HEAPNAM:near,A_DCHDR:near,A_BUF:near
extrn A_SBDIR:near,A_ALBLK:near
ENDIF
IFB <nopush>
pushad
pushfd
ENDIF
IFIDN <kind>,<OFT>
a = 1
mov eax,objs
call A_OFT ; assert OFT
ENDIF
IFIDN <kind>,<SECPTR>
a = 1
lea eax,objs
call A_SECPTR ; returns 'C' clear if hint field is valid
ENDIF
IFIDN <kind>,<ALBLK>
a = 1
mov eax,objs
call A_ALBLK
ENDIF
IFIDN <kind>,<ASREC>
a = 1
mov eax,objs
call A_AS
ENDIF
IFIDN <kind>,<HEAPNAM>
a = 1
mov eax,objs
call A_HEAPNAM
ENDIF
IFIDN <kind>,<DCHDR>
a = 1
mov edx,arg1
mov eax,objs
call A_DCHDR
ENDIF
IFIDN <kind>,<DIRBLK>
a = 1
mov eax,objs
call A_DIRBLK
ENDIF
IFIDN <kind>,<BUF>
a = 1
mov eax,objs
call A_BUF
ENDIF
IFIDN <kind>,<SBDIR>
a = 1
mov eax,objs
call A_SBDIR
ENDIF
IFIDN <kind>,<FNODE>
a = 1
mov eax,objs
call A_FNODE
ENDIF
IFE a
.error illegal option
ENDIF
IFB <nopush>
popfd
popad
nop ; errata
ENDIF
ENDM
ELSE
ASSERT Macro a,b,c
ENDM
ENDIF
;** Heap sanity check macro (controlled by DEBUG flag)
;
; item - make sure this points to a heap allocated block
; (return value from GHS or GHS_)
; if blank, just the arena is checked.
IFDEF DEBUG
HeapChk Macro item
ifndef A_HEAP
extrn A_HEAP:near
endif
push edx
ifb <item>
mov edx, 0 ;; don't zap the flags
endif
ifdif <edx>, <item>
mov edx, item
endif
call A_HEAP
pop edx
ENDM
ELSE
HeapChk Macro item
ENDM
ENDIF
DPUBLIC MACRO arg
ifdef DEBUG
Public arg
endif
ENDM
BREAK MACRO subtitle
SUBTTL subtitle
PAGE
ENDM
;** CalcGBHShift - calculate the GBH shift factor
GBHShift = 0
CalcGBHShift MACRO
local ?tmp
if GBHShift NE 0
EXITM
endif
?tmp = (SECSIZE*SPB) / (size BUFNODE)
rept 16
if ?tmp EQ 1
exitm
endif
?tmp = ?tmp / 2
GBHShift = GBHShift + 1
endm
.errnz SECSIZE * SPB - ((size BUFNODE) SHL GBHShift)
ENDM
;** GBH - Get Buffer Header
;
; GBH takes the address of a buffer data area and returns the
; address of it's header.
;
; Since the data area is linear in memory and the headers are linear,
; we just do a simple linear mapping.
;
; GBH transforms the address in the register without modifying
; any other registers.
;
; GBH reg
GBH MACRO reg
CalcGBHShift
sub reg,Bufbase ; (reg) = offset in array of buffers
shr reg,GBHShift ; (reg) = offset in array of bufnotes
; Get rid of low order stuff. Since reg may be an offset WITHIN
; a buffer and not just a poitner to the header itself, we mask off the
; low order stuff.
ifidn <reg>,<eax>
and al,100h - (SIZE bufnode)
else
ifidn <reg>,<ebx>
and bl,100h - (SIZE bufnode)
else
ifidn <reg>,<ecx>
and cl,100h - (SIZE bufnode)
else
%out add more code to this macro
.err
endif
endif
endif
add reg, OFFSET DS:Bhbase
ENDM
;* RetHeap - Return Heap Item
;
; RetHeap address-of-item
RetHeap MACRO reg
HeapChk reg
add dword ptr -4[reg],80000000h-4
ENDM
;* GetPerm - Get Perminant Memory
;
; Returns a block of memory which will be perminantly
; occupied
GetPerm Macro reg,len
local l1,l2
l1: mov reg,PermPtr
add PermPtr,len
cmp reg,PermLim
jb short l2
push len
call aapm ; allocate additional perm memory
jmp l1
align 4
l2:
ENDM
BREAK <Double Chain Manipulation Macros>
;** The following macros manipulate double-linked lists.
;
; All macros take as their first argument the offset to
; the pointer pair.
;** DCADDB - Add Item to Back of List
;
; DCADDB offset,listreg,itemreg,scrreg
;
; offset = offset into structure of links to edit
; listreg = address of list head node
; itemreg = address of item to insert
; scrreg = scratch register to roach
DCADDB MACRO o,LR,IR,SR
mov SR,o.BAK[LR]
mov o.FWD[SR],IR
mov o.FWD[IR],LR
mov o.BAK[IR],SR
mov o.BAK[LR],IR
ENDM
;** DCADDF - Add Item to Front of List
;
; DCADDF offset,listreg,itemreg,scrreg
;
; offset = offset into structure of links to edit
; listreg = address of list head node
; itemreg = address of item to insert
; scrreg = scratch register to roach
DCADDF MACRO o,LR,IR,SR
mov SR,o.FWD[LR]
mov o.FWD[IR],SR
mov o.BAK[IR],LR
mov o.BAK[SR],IR
mov o.FWD[LR],IR
ENDM
;** DCREM - Remove Item from Double Link Chain
;
; DCREM offset,adrreg,scrreg1,scrreg2
;
; offset = offset into structure of links to edit
; adrreg = address of item to remove
; scrreg? = two registers to scratch
DCREM MACRO o,ir,r2,r3
mov r2,o.FWD[ir]
mov r3,o.BAK[ir]
mov o.BAK[r2],r3
mov o.FWD[r3],r2
ENDM
;** DCMOVF - Move Item to the Front of the Chain
;
; DCMOVF offset,listreg,itemreg,scrreg,[scrreg2]
;
; offset = offset into structure of links to edit
; listreg = address of list head node
; itemreg = address of item to insert
; scrreg = scratch register to roach
; scrreg2 = optional additional register to roach
;
; BUGBUG - check users for supply of scratch registers
DCMOVF MACRO o,lr,ir,sr,sr2
IFNB <sr2>
DCREM o,ir,sr,sr2
else
push lr
DCREM o,ir,lr,sr
pop lr
endif
DCADDF o,lr,ir,sr
ENDM
;** DCMOVB - Move Item to the Back of the Chain
;
; DCMOVB offset,listreg,itemreg,scrreg
;
; offset = offset into structure of links to edit
; listreg = address of list head node
; itemreg = address of item to insert
; scrreg = scratch register to roach
DCMOVB MACRO o,lr,ir,sr
push lr
DCREM o,ir,lr,sr
pop lr
DCADDB o,lr,ir,sr
ENDM
;** ADDHASH - add a buffer to hash list
;
; ADDHASH lsn,buf,sr1,sr2,sr3
;
; lsn = Vsector or Psector number of beginning of buffer
; may be any of the arg registers
; buf = address of buffer header
; sr1 = scratch register
; sr2 = 'nother scratch register
; sr3 = last scratch register
ADDHASH MACRO lsn,buf,sr1,sr2,sr3
local l1,l2
mov sr1,lsn
and sr1,(HASHCNT-1)*4 ; (sr1) = hash index
add sr1,offset DGROUP:HashTab
mov B_HTA[buf],sr1 ; save hash ptr for later use by DCADDF
mov sr2,[sr1]
ifidn <sr2>,<ecx>
jecxz l1
else
and sr2,sr2
jz short l1 ; nobody on list yet
endif
DCADDF B_HASH,sr2,buf,sr3 ; add to hash list
jmp short l2
align 4
l1: mov B_HASH.FWD[buf],buf ; empty list, make self-linked
mov B_HASH.BAK[buf],buf
l2: mov [sr1],buf ; put our guy at front of chain
ENDM
;** HASHFIND - find a sector in the hash
;
; HASHFIND lsn,buf,sr1,fnd
;
; lsn = logical sector number to find. HASHFIND presumes it
; has already been rounded to a multiple of SPB
; buf = register where buffer is returned
; sr1 = scratch register
; fnd = where to go if found
; NOTE: falls through if not found
HASHFIND MACRO lsn,buf,sr1,fnd
local l1,l2
mov sr1,lsn
and sr1,(HASHCNT-1)*4 ; (sr1) = hash index
mov buf,Hashtab[sr1]
ifidn <buf>,<ecx>
jecxz l2
else
and buf,buf
jz short l2 ; no entries in chain, block not there
endif
mov sr1,buf ; save address of first guy
; Run through circular chain, looking for a match.
;
; (buf) = next guy to check out
; (lsn) = sector value to match
; (sr1) = address of first guy in chain
align 4
l1: cmp lsn,B_SEC[buf]
je fnd ; got him
mov buf,B_HASH.FWD[buf] ; go to next buffer
cmp buf,sr1 ; have we gone around yet?
jne l1 ; no, go examine buffer
l2:
ENDM
;** FALLTHRU - Verifies Fallthrough Validity
FALLTHRU MACRO labl
align 4 ; don't have errnz fail due to alignment
IF2 ; of following label
.errnz labl-$
ENDIF
ENDM
;** INTERR - Internal Error
; INTERRnz - Internal error iff 'Z' clear
; INTERRzr - Internal error iff 'Z' set
; INTERRc - Internal error if 'C' set
ifdef DEBUG
INTERR MACRO
local l
l: int 3
jmp l
ENDM
INTERRzr MACRO
local l
jnz short l
int 3
jmp $-1
l:
ENDM
INTERRc MACRO
local l
jnc short l
int 3
jmp $-1
l:
ENDM
INTERRnz MACRO
local l
jz short l
int 3
jmp $-1
l:
ENDM
else
INTERR MACRO
ENDM
INTERRzr MACRO
ENDM
INTERRc MACRO
ENDM
INTERRnz MACRO
ENDM
endif
;* Debug Traps
;
; These are removed as the code is exercised
TRAPC macro
local l
jnc short l
int 3
l:
ENDM
TRAPZ macro
local l
jnz short l
int 3
l:
ENDM
TRAPNZ macro
local l
jz short l
int 3
l:
ENDM
;** PANIC - Panic File System
;
; BUGBUG - fix me to do something besides trap
PANIC macro
local l
l: int 3
jmp l
ENDM
;** Bulk Register Save/Restore
;
SAVE MACRO reglist
IRP reg,<reglist>
PUSH reg
ENDM
ENDM
.xcref SAVE
RESTORE MACRO reglist ;; pop those registers
IRP reg,<reglist>
POP reg
ENDM
ENDM
.xcref RESTORE
;* ret16 - perform a 16bit return
;
; If we are in a use32 segment then we must put out an operand size
; override before the ret.
ret16 macro stkfix
ife @WordSize - 4
db 66h ;; operand size override
endif
retf stkfix
endm
.xcref ret16
;* call1616 - perform an indirect 16bit far call
;
; If we are in a use32 segment then we must put out an operand size
; override before the call and then cast the target to "FWORD" so that
; MASM will generate the correct instruction.
;
; The target must be indirect.
call1616 macro target
.errnz (type target) - 4
ife @WordSize - 4
db 66h ;; operand size override
call fword ptr target ;; force indirect far call
else
call target
endif
endm
.xcref call1616
;** Dpush - Push 32-bit constant
;
; MASM has no way of expressing this in USE16 mode.
DPUSH macro a
ifdef USE32
push a
else
push a ; low order
push 0
endif
ENDM
;** Push16 - generate a 16bit push in a 32-bit code segment. This is
; needed when pushing segment regs and immediate values as arguments
; to 16bit procedures.
push16 macro operand
db 66h
push operand
endm
;** STATINC - Do an INC if STAT gathering is enabled
;
; Preserves 'C'
STATINC macro a
ifdef STATS
inc a
endif
ENDM
;** STATDEC - Do an DEC if STAT gathering is enabled
;
; Preserves 'C'
STATDEC macro a
ifdef STATS
dec a
endif
ENDM
;** LogHCNT - Log OFT holding/unholding
;
ifdef DEBUG
LOGHCNT MACRO reg
ifndef DoLogHcnt
EXTRN DoLogHcnt:near
endif
pushfd
push eax
mov eax,reg
call DoLogHcnt
pop eax
popfd
ENDM
;** LogSCNT - Lock SBDIR holding/unholding
;
LOGSCNT MACRO REG
ifndef DoLogScnt
EXTRN DoLogScnt:near
endif
pushfd
push eax
ifdif <REG>,<eax>
mov eax,reg
endif
call DoLogScnt
pop eax
popfd
ENDM
else
LOGHCNT MACRO
ENDM
LOGSCNT MACRO
ENDM
endif
ifdef DEBUG
CALLVBS MACRO
ifndef VBS
EXTRN VBS:NEAR
endif
call VBS
ENDM
else
CALLVBS MACRO
ENDM
endif
;** cBUFZAP - Call DoZap iff debug mode set
;
cBUFZAP Macro
ifdef DEBUG
ifndef DoZap
EXTRN DoZap:near
endif
call DoZap
endif
endm
;** Stack Frame Macros
;
; These macros are used to allow a stack frame to be setup by
; simple PUSHES and yet guarantee that the pushes won't drift
; out of sync with the frame declaration.
LASTEL MACRO struc,elem
.errnz size struc - elem - size elem
?frof = elem
ENDM
NEXTEL MACRO elem
.errnz ?frof - elem - size elem
?frof = elem
ENDM
DUMYEL MACRO si
?frof = ?frof - si
ENDM
FIRSTEL MACRO elem
.errnz ?frof - size elem
?frof = elem
.errnz elem
ENDM
;** CHKSECNUM - Check Sector number
;
; CHKSECNUM reg
;
; Make sure that reg has a sector number in it without the high order
; volume ID bits
CHKSECNUM MACRO reg
local l1
ifdef DEBUG
test reg,NOT SECMASK
jz l1
INTERR
l1:
endif
ENDM