home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / OS2-ST01 / dosmac.inc < prev    next >
Text File  |  1989-06-06  |  32KB  |  1,679 lines

  1. ;
  2. ; copyright (C) Microsoft, 1988
  3. ;
  4. ;
  5. FALSE    equ    0
  6. TRUE    equ    not FALSE
  7.  
  8. AsmVars    macro    varlist, value
  9.     irp var,<varlist>
  10.     AsmVar var, value
  11.     endm
  12. endm
  13.  
  14. AsmVar    macro    var, value
  15.     ifndef var
  16.     ifb <value>
  17.         var = FALSE
  18.     else
  19.         var = <value>
  20.     endif
  21.     endif
  22. endm
  23.  
  24.  
  25. ;    Check if all (or most) the checking flags are to be enabled.
  26.  
  27. ifdef ALLSTRICT
  28.     AsmVar MISCSTRICT, TRUE
  29.     AsmVar VMSTRICT,   TRUE
  30.     AsmVar DEVSTRICT,  TRUE
  31.     AsmVar VOLPTRCHK,  TRUE
  32.     AsmVar INTERRPRT,  TRUE
  33.     AsmVar DHSTRICT,   TRUE
  34.     AsmVar SELSTRICT,  TRUE
  35.     AsmVar FSSTRICT,   TRUE
  36. endif
  37.  
  38.  
  39. ;*  Values for ?farcode, set by FARCODE macro to indicate which
  40. ;   code segment is being assembled.
  41.  
  42. FC_DosCode    EQU    0        ; DosCode
  43. FC_InitCode    EQU    1        ; DosInitCode
  44. FC_HighCode    EQU    2        ; DosHighCode
  45. FC_High2Code    EQU    3        ; DosHigh2Code
  46. FC_Ring3Code    EQU    4        ; DosRing3Code
  47. FC_InitRMCode    EQU    5        ; DosInitRMCode
  48.  
  49. SUBTTL BREAK a listing into pages and give new subtitles
  50. PAGE
  51. BREAK    MACRO    subtitle
  52.     SUBTTL    subtitle
  53.     PAGE
  54. ENDM
  55. .xcref    BREAK
  56.  
  57. ;
  58. ; call a procedure that may be external.  The call will be short.
  59. ;
  60. invoke    MACRO    name
  61. .xcref
  62. IF2
  63. IFNDEF name
  64.     EXTRN    name:NEAR
  65. ENDIF
  66. ENDIF
  67. .cref
  68.     CALL    name
  69. ENDM
  70. .xcref    invoke
  71.  
  72.  
  73. PAGE
  74. ;
  75. ; jump to a label that may be external.  The jump will be near.
  76. ;
  77. transfer    MACRO   name
  78. .xcref
  79. IF2
  80. IFNDEF name
  81.     EXTRN    name:NEAR
  82. ENDIF
  83. ENDIF
  84. .cref
  85.     JUMP    name
  86. ENDM
  87. .xcref    transfer
  88.  
  89.  
  90. ;
  91. ; get a short code address in a word
  92. ;
  93.  
  94. CSOFFSET EQU OFFSET DosCode:
  95.  
  96. short_addr  MACRO   name
  97. IFDIF    <name>,<?>
  98. .xcref
  99. IF2
  100. IFNDEF name
  101.     EXTRN    name:NEAR
  102. ENDIF
  103. ENDIF
  104. .cref
  105.     DW  CSOFFSET name
  106. ELSE
  107.     DW  ?
  108. ENDIF
  109. ENDM
  110. .xcref    short_addr
  111.  
  112.  
  113. ;
  114. ; get a long address in a dword
  115. ;
  116. long_addr   MACRO   name
  117. .xcref
  118. IF2
  119. IFNDEF name
  120.     EXTRN    name:NEAR
  121. ENDIF
  122. ENDIF
  123. .cref
  124.     DD  name
  125. ENDM
  126. .xcref    long_addr
  127.  
  128. ;    Declare a Procedure:
  129. ;    Parameters:
  130. ;      name: procedure_name
  131. ;      distance: near,far,hybrid,faronly
  132. ;      scope: local,farlocal,nearlocal
  133. ;      treg: scratch register
  134. ;        If non-blank, this register is used to optimizize far calls
  135. ;        to hybrid procedures, at the expense of near calls.
  136. ;        By default, near calls are the more efficient of the two.
  137. ;      abase: the number of bytes to skip for calculating the ArgVar
  138. ;         offsets. The default (if this is blank) depends on the
  139. ;         "distance" variable. "NEAR" is 4 and "FAR" is 6.
  140.  
  141. .xcref    ?frame
  142. .xcref    ?aframe
  143. .xcref    ?abase
  144. .xcref    ?stackdepth
  145. .xcref    ?initstack
  146. ?frame        =  0    ; initial
  147. ?aframe     =  0    ; initial
  148. ?abase        =  0    ; initial
  149. ?stackdepth =  0    ; initial stack size
  150. ?initstack  =  0    ; initial stack size
  151. ?local        =  0    ; local proc flag
  152. ?near        =  0    ; near proc flag
  153. ?faronly    =  0    ; faronly proc flag
  154. ?oldfaronly =  0    ; outer scope faronly proc flag
  155. ?depth        =  0    ; procedure nesting level
  156.  
  157. Procedure macro   name,distance,scope,treg,abase
  158.     if2
  159.     if ?depth gt 1
  160.         %out Nesting too deep in Procedure name
  161.         .err
  162.     endif
  163.     endif
  164.     ?depth    = ?depth + 1
  165.     ?oldfaronly = ?faronly    ;; save previous value
  166.     ?frame    = 0
  167.     ?aframe    = 0
  168.     ?faronly    = 0        ;; default to near/hybrid
  169.     ?near    = 1        ;; default to near
  170.     ?initstack    = ?stackdepth    ;; beginning of procedure
  171.     ?local    = 0        ;; default to public
  172.     ifnb <scope>
  173.     ?local = 1        ;; local if non-blank scope
  174.     if2
  175.         ?x = 0
  176.         irp x,<LOCAL,local,farlocal,nearlocal>
  177.         ifidn <x>,<scope>
  178.             ?x = 1
  179.         endif
  180.         endm
  181.         ife ?x
  182.         %out Bad scope_arg scope in Procedure name
  183.         ;;.err
  184.         endif
  185.     endif
  186.     endif
  187.     ifnb <distance>        ;; if nonblank, is hybrid, near, faronly or far
  188.     if2
  189.         ?x = 0
  190.         irp x,<HYBRID,hybrid,NEAR,near,FAR,far,FARONLY,faronly>
  191.         ifidn <x>,<distance>
  192.             ?x = 1
  193.         endif
  194.         endm
  195.         ife ?x
  196.         %out Bad distance_arg distance in Procedure name
  197.         ;;.err
  198.         endif
  199.     endif
  200.     irp x,<HYBRID,hybrid>
  201.         ?local = 0
  202.         ifidn <scope>,<local>
  203.         ?local = 1            ;; local if scope is 'local'
  204.         endif
  205.         ifidn <scope>,<LOCAL>
  206.         ?local = 1            ;; local if scope is 'LOCAL'
  207.         endif
  208.         ifidn <distance>,<x>
  209.         ifb <treg>
  210.             ifidn <scope>,<nearlocal>
  211.             GENHYBRID name        ;; generate far public thunk
  212.             ?local = 1        ;; but near label is local
  213.             else
  214.             GENHYBRID name,<scope>    ;; generate far thunk
  215.             endif
  216.         else
  217.             ifidn <scope>,<farlocal>
  218.             Entry name        ;; generate near public label
  219.             ?local = 1        ;; but far label is local
  220.             else
  221.             Entry name,,<scope>
  222.             endif
  223.             pop  treg
  224.             push cs
  225.             push treg
  226.             ?faronly = 1    ;; pretend to be faronly
  227.             ?near    = 0    ;; not near
  228.         endif
  229.         endif
  230.     endm
  231.     irp x,<FAR,far>
  232.         ifidn <distance>,<x>
  233.         ?near = 0        ;; is far
  234.         endif
  235.     endm
  236.     irp x,<FARONLY,faronly>
  237.         ifidn <distance>,<x>
  238.         ?faronly = 1    ;; is faronly
  239.         ?near     = 0    ;; not near
  240.         endif
  241.     endm
  242.     endif
  243.     if ?faronly
  244.     if ?local
  245.         GENPUBLIC hy_&name,<local>,code
  246.     else
  247.         GENPUBLIC hy_&name,,code
  248.     endif
  249.     else
  250.     if ?local
  251.         GENPUBLIC name,<local>,code
  252.     else
  253.         GENPUBLIC name,,code
  254.     endif
  255.     endif
  256.     if ?near
  257.     ?abase = 2+2        ;; remember the pushed BP
  258.     name proc near        ;; is near or hybrid
  259.     else
  260.     ?abase = 4+2        ;; remember the pushed BP
  261.     if ?faronly
  262.         hy_&name proc far    ;; is faronly
  263.     else
  264.         name proc distance    ;; else must be far
  265.     endif
  266.     endif
  267.     ifnb <abase>        ;; if abase is not blank, then use it
  268.     ?abase = abase
  269.     endif
  270. endm
  271. .xcref    procedure
  272.  
  273. ;
  274. ; end a procedure and check that stack depth is preserved
  275. ;
  276. EndProc macro    name, chk
  277.     ifdif <chk>,<NoCheck>    ;; check the stack size
  278.     if2
  279.         if ?initstack ne ?stackdepth ;; is it different?
  280.         %out ***** Possible stack size error in name *****
  281.         endif
  282.     endif
  283.     endif
  284.     if ?faronly
  285.     hy_&name endp        ;; is faronly
  286.     else
  287.     name endp            ;; else near, far or hybrid
  288.     endif
  289.     ife ?depth
  290.     if2
  291.         %out EndProc without matching Procedure name
  292.         .err
  293.     endif
  294.     else
  295.     ?depth = ?depth - 1
  296.     ?faronly = ?oldfaronly    ;; restore previous value
  297.     endif
  298.     ifdef KILLASSUMES
  299.     assume ds:nothing, es:nothing, ss:nothing
  300.     endif
  301. endm
  302. .xcref    EndProc
  303.  
  304.  
  305. ;**    GENPUBLIC - generate a public symbol in all cases, but first
  306. ;    pervert the name if it really is a local symbol.  For symbolic
  307. ;    debugger support only.
  308.  
  309. ?lcnt = 0
  310. GENPUBLIC macro name,local,code        ;; generate a public or local symbol
  311.     ifb <local>                ;; if local symbol not requested
  312.     public name
  313.     else
  314.     ifdef NOLOCAL            ;; if all symbols should be public
  315.         public name
  316.     else
  317.         ?GENLOCAL %?lcnt,name,<code> ;; else croft a local (pseudo public)
  318.         ?lcnt = ?lcnt + 1
  319.     endif
  320.     endif
  321. endm
  322.  
  323. ?GENLOCAL macro cnt,name,code        ;; generate a public local symbol
  324.     public l&cnt&_&name
  325.     ifb <code>
  326.     l&cnt&_&name label byte        ;; allow masm PUBDEF DS association
  327.     else
  328.     l&cnt&_&name:            ;; avoid masm PUBDEF DS association
  329.     endif
  330. endm
  331.  
  332.  
  333. ;**    EXTRNFAR - generate an EXTRN for the hybrid symbol if it
  334. ;    has not yet been defined, and the skip argument is blank.
  335.  
  336. EXTRNFAR macro    name,skip
  337. ifb <skip>
  338.     ifndef hy_&name
  339.     extrn    hy_&name:far
  340.     endif
  341. endif
  342. endm
  343.  
  344.  
  345. ; generate a far pointer to a hybrid procedure
  346.  
  347. DDFAR    macro name
  348.     dd    hy_&name
  349. endm
  350.  
  351.  
  352. ; move the offset of a hybrid procedure into a register or memory
  353.  
  354. MOVFAROFFSET macro target,name,group
  355. ifb <group>
  356.     mov    target,offset cs:hy_&name
  357. else
  358.     mov    target,offset group:hy_&name
  359. endif
  360. endm
  361.  
  362.  
  363. ; generate an intersegment call or jmp to a hybrid procedure
  364.  
  365. CALLFAR macro    name
  366.     call    far ptr hy_&name
  367. endm
  368.  
  369. JMPFAR    macro    name
  370.     jmp    far ptr hy_&name
  371. endm
  372.  
  373.  
  374. ; generate a hybrid procedure linkage procedure
  375.  
  376. GENHYBRID macro name,lcl
  377. local farproc
  378.     farproc proc far
  379.     ret
  380.     GENPUBLIC hy_&name,<lcl>        ;; generate a public or local symbol
  381.     hy_&name label far
  382.     push    offset cs:farproc    ;; near-code must immediately follow
  383.     farproc endp
  384. endm
  385.  
  386.  
  387. ; generate a near/far/hybrid entry into a procedure
  388.  
  389. Entry macro name,distance,scope
  390. local a
  391. a = 0                ;; assume near label
  392. ifnb <scope>
  393.     if2
  394.     ?x = 0
  395.     irp x,<local,LOCAL>
  396.         ifidn <x>,<scope>
  397.         ?x = 1
  398.         endif
  399.     endm
  400.     ife ?x
  401.         %out Bad scope_arg scope in Entry name
  402.         ;;.err
  403.     endif
  404.     endif
  405. endif
  406. ifnb <distance>
  407.     if2
  408.     ?x = 0
  409.     irp x,<faronly,hybrid,HYBRID>
  410.         ifidn <x>,<distance>
  411.         ?x = 1
  412.         endif
  413.     endm
  414.     ife ?x
  415.         %out Bad distance_arg distance in Entry name
  416.         ;;.err
  417.     endif
  418.     endif
  419.     ifidn <distance>,<faronly>    ;; was it far only?
  420.     a = 1            ;; then generate far label
  421.     else            ;; else must be hybrid
  422.     jmp short name        ;; previous callers skip hybrid linkage
  423.     GENHYBRID name,<scope>
  424.     endif
  425. endif
  426. if a                ;; generate far label?
  427.     GENPUBLIC hy_&name,<scope>    ;; generate a public or local symbol
  428.     hy_&name:
  429. else                ;; else generate near label
  430.     GENPUBLIC name,<scope>    ;; generate a public or local symbol
  431.     name:
  432. endif
  433. endm
  434. .xcref    Entry
  435.  
  436. BREAK <ERROR - store an error code then jump to a label>
  437.  
  438. error macro code
  439. .xcref
  440.     mov    al,code
  441.     transfer Sys_Ret_Err_AL
  442. .cref
  443. ENDM
  444. .xcref    error
  445.  
  446. BREAK <JUMP - real jump that links up shortwise>
  447. ;
  448. ; given a label <lbl> either 2 byte jump to another label <lbl>_J
  449. ; if it is near enough or 3 byte jump to <lbl>
  450. ;
  451.  
  452. jump    macro lbl
  453.     local a
  454. .xcref
  455.  
  456.     ifndef lbl&_J        ;; is this the first invocation
  457. a:  JMP lbl
  458.     ELSE
  459.     IF (lbl&_J GE $) OR ($-lbl&_J GT 126)
  460. a:  JMP lbl        ;; is the jump too far away?
  461.     ELSE
  462. a:  JMP lbl&_J        ;; do the short one...
  463.     ENDIF
  464.     ENDIF
  465.     lbl&_J = a
  466. .cref
  467. endm
  468. .xcref    jump
  469.  
  470. BREAK <RETURN - return from a function>
  471.  
  472. return    macro x
  473.     local a
  474. .xcref
  475. a:
  476.     RET
  477. ret_l = a
  478. .cref
  479. endm
  480. .xcref    return
  481.  
  482. BREAK <CONDRET - conditional return>
  483.  
  484. condret macro    cc,ncc
  485.     local    a
  486. .xcref
  487. .xcref a
  488. .cref
  489.     ifdef    ret_l        ;; if ret_l is defined
  490.     if (($ - ret_l) le 126) and ($ gt ret_l)
  491.                     ;;     if ret_l is near enough then
  492.         a:  j&cc    ret_l    ;;     a: j<CC> to ret_l
  493.         ret_&cc = a        ;;       define ret_<CC> to be a:
  494.         exitm
  495.     endif
  496.     endif
  497.     ifdef    ret_&cc     ;; if ret_<CC> defined
  498.     if (($ - ret_&cc) le 126) and ($ gt ret_&cc)
  499.                     ;;     if ret_<CC> is near enough
  500.         a:  j&cc    ret_&cc    ;;     a: j<CC> to ret_<CC>
  501.         ret_&cc = a        ;;       define ret_<CC> to be a:
  502.         exitm
  503.     endif
  504.     endif
  505.     j&ncc    a        ;; j<NCC> a:
  506.     return            ;; return
  507.     a:            ;; a:
  508.     ret_&cc = ret_l     ;; define ret_<CC> to be ret_l
  509. endm
  510. .xcref    condret
  511.  
  512. BREAK <RETZ - return if zero, links up shortwise if necessary>
  513.  
  514. retz    macro
  515.     condret z,nz
  516. endm
  517. .xcref    retz
  518.  
  519. BREAK <RETNZ - return if not zero, links up shortwise if necessary>
  520.  
  521. retnz    macro
  522.     condret nz,z
  523. endm
  524. .xcref    retnz
  525.  
  526. BREAK <RETC - return if carry set, links up shortwise if necessary>
  527.  
  528. retc    macro
  529.     condret c,nc
  530. endm
  531. .xcref    retc
  532.  
  533. BREAK <RETNC - return if not carry, links up shortwise if necessary>
  534.  
  535. retnc    macro
  536.     condret nc,c
  537. endm
  538. .xcref    retnc
  539.  
  540. BREAK <CONTEXT - set the DOS context to a particular register>
  541.  
  542. Dos3Mac MACRO name
  543. IF2
  544.     %out    Warning - DOS 3 macro name called
  545. ENDIF
  546. ENDM
  547.  
  548.  
  549. SegContext macro    srl,gr,noassume,base,grpnam
  550. IFB <gr>            ;; push and pop if no general register
  551.     IRP sr,<srl>        ;; for each register
  552.     PUSH    base        ;; push base
  553.     POP    sr        ;; pop into the register
  554.     IFB <noassume>        ;; if ASSUME not inhibited
  555.         ASSUME    sr:grpnam
  556.     ENDIF
  557.     ENDM
  558. ELSE                ;; else if we have a helper register
  559.     MOV     gr,base        ;; load helper with base
  560.     IRP sr,<srl>        ;; for each register in list
  561.     MOV    sr,gr        ;; load the register from the helper
  562.     IFB <noassume>        ;; if ASSUME not inhibited
  563.         ASSUME    sr:grpnam
  564.     ENDIF
  565.     ENDM
  566. ENDIF
  567. endm
  568. .xcref    SegContext
  569.  
  570.  
  571. DosContext macro    srl,gr,noassume
  572. LOCAL i
  573.     IFNB <gr>                ;; if intermediate general register
  574.     mov    gr,DosGroup
  575.     IRP sr,<srl>
  576.         mov     sr,gr
  577.     ENDM
  578.     ELSE
  579.     IRP sr,<srl>            ;; for sr = *first* segreg in list
  580.         i = 0
  581.         IRP r,<srl>         ;;  for r = each segreg in list
  582.         i = i + 1
  583.         IF i EQ 1        ;; if r is first in list
  584.             push    DosGroup    ;; do push immediate
  585.         ELSE            ;; else r is second (or later) in list
  586.             push    sr        ;; and sr contains desired value
  587.         ENDIF
  588.         pop    r
  589.         ENDM
  590.         EXITM            ;; quit after sr = first in list
  591.     ENDM
  592.     ENDIF
  593.     IFB <noassume>
  594.     IRP sr,<srl>
  595.         ASSUME  sr:DosGroup
  596.     ENDM
  597.     ENDIF
  598. endm
  599. .xcref    DosContext
  600.  
  601.  
  602. DosHighContext macro   srl,gr,noassume
  603.     SegContext   <srl>,gr,noassume,DosHighData,DosHighData
  604. endm
  605. .xcref    DosHighContext
  606.  
  607.  
  608. TaskContext macro   srl,gr,noassume
  609.     SegContext   <srl>,gr,noassume,SS,TaskArea
  610. endm
  611. .xcref    TaskContext
  612.  
  613.  
  614. DosInitContext macro   srl,gr,noassume
  615.     SegContext   <srl>,gr,noassume,DosInitData,DosInitData
  616. endm
  617. .xcref    DosInitContext
  618.  
  619.  
  620. BREAK <SaveReg/RestoreReg - save or restore a set of registers>
  621.  
  622. SaveReg MACRO    reglist     ;; push those registers
  623. IRP reg,<reglist>
  624.     ?stackdepth = ?stackdepth + 1
  625.     PUSH    reg
  626. ENDM
  627. ENDM
  628. .xcref    SaveReg
  629.  
  630. RestoreReg  MACRO   reglist    ;; pop those registers
  631. IRP reg,<reglist>
  632.     ?stackdepth = ?stackdepth - 1
  633.     POP reg
  634. ENDM
  635. ENDM
  636. .xcref    RestoreReg
  637.  
  638. BREAK <Critical section macros>
  639.  
  640. ifdef INTERRPRT
  641.     IntErrF = TRUE
  642. endif
  643.  
  644. AsmVars <Debug,IntErrF,ShareF,Redirector>
  645.  
  646. BREAK    <DOSAssume - validate assumes>
  647.  
  648. DOSAssume   Macro   reg,reglist,message
  649. local a,b
  650. IFIDN <reg>,<CS>
  651.     $temp    =   1
  652. ELSE
  653.     IFIDN <reg>,<SS>
  654.         $temp    =   0
  655.     ELSE
  656.         IFIDN <reg>,<DOS>
  657.             IF Redirector
  658.                 $temp = 8
  659.             ELSE
  660.                 $temp = 1
  661.             ENDIF
  662.         ELSE
  663.             %out ***** Invalid DOS register reg in DOSAssume *****
  664.         ENDIF
  665.     ENDIF
  666. ENDIF
  667. IF Debug
  668.     IRP r,<reglist>
  669.         IFIDN <r>,<DS>
  670.             $temp = $temp OR 2
  671.         ELSE
  672.             IFIDN <r>,<ES>
  673.                 $temp = $temp OR 4
  674.             ELSE
  675.                 %out ***** Invalid register r in DOSAssume *****
  676.             ENDIF
  677.         ENDIF
  678.     ENDM
  679.     PUSH    AX
  680.     MOV AX,$temp
  681.     PUSH    AX
  682. IF ShareF OR Redirector
  683.     MOV AX,OFFSET b
  684. ELSE
  685.     MOV AX,OFFSET DosGroup:b
  686. ENDIF
  687.     PUSH    AX
  688.     Invoke    SegCheck
  689.     POP AX
  690. IF ShareF OR Redirector
  691.     JMP SHORT a
  692. b   DB    message,0
  693. a:
  694. ELSE
  695. Table segment
  696. b   DB    message,0
  697. Table ends
  698. ENDIF
  699. ENDIF
  700. IRP r,<reglist>
  701.     IF $temp AND 1
  702.         IF Redirector
  703.             ASSUME    r:NETWRK
  704.         ELSE
  705.             ASSUME    r:DosGroup
  706.         ENDIF
  707.     ELSE
  708.         IF $temp AND 8
  709.             ASSUME    r:DosGroup
  710.         ELSE
  711.             ASSUME    r:TaskArea
  712.         ENDIF
  713.     ENDIF
  714. ENDM
  715. ENDM
  716.  
  717. BREAK    <ASSERT - make assertions about registers>
  718. ;*  Assert - sanity checks (contolled by DEBUG switch)
  719. ;
  720. ;   kind:   one of Z, NZ, ISBUF, ISCURBUF, ISSFT, ISVPB (case is
  721. ;        significant)
  722. ;   objs:   register pair which should point to given structure
  723. ;        for IS???; an expression for Z or NZ
  724. ;   message: message printed if assertion fails; should identify
  725. ;        the calling routine
  726.  
  727. IF Debug
  728. Assert    MACRO    kind, objs, message
  729.     LOCAL    a,b
  730.     IFIDN    <kind>,<Z>
  731.     CMP objs,0
  732.     JZ  a
  733.     DBPRT    <>,<>,<message>
  734. a:
  735.     ELSE
  736.     IFIDN    <kind>,<NZ>
  737.     CMP objs,0
  738.     JNZ a
  739.     DBPRT    <>,<>,<message>
  740. a:
  741.     ELSE
  742.         IFIDN    <kind>,<ISDPB>
  743. %out ISDPB referenced... Needs to be examined (someday) and changed to ISVPB
  744.     EXITM
  745.         ENDIF
  746.     PUSH    AX
  747.         IRP obj,<objs>
  748.     PUSH    obj
  749.         ENDM
  750.         IF ShareF
  751.     MOV    AX,OFFSET b
  752.         ELSE
  753.     MOV    AX,OFFSET DosGroup:b
  754.         ENDIF
  755.     PUSH    AX
  756.         IFIDN    <kind>,<ISBUF>
  757.     Invoke    BUFCheck
  758.         ENDIF
  759.         IFIDN    <kind>,<ISCURBUF>
  760.     Invoke    CURBUFCheck
  761.         ENDIF
  762.         IFIDN    <kind>,<ISSFT>
  763.     Invoke    SFTCheck
  764.         ENDIF
  765.         IFIDN    <kind>,<ISVPB>
  766.     Invoke    xVPBCheck
  767.         ENDIF
  768.     POP    AX
  769.         IF ShareF
  770.     JMP SHORT a
  771. b   DB    message,0
  772. a:
  773.         ELSE
  774. Table    segment
  775. b   DB    message,0
  776. Table    ends
  777.         ENDIF
  778.     ENDIF
  779.     ENDIF
  780. ENDM
  781. ELSE
  782. Assert    Macro
  783. ENDM
  784. ENDIF
  785.  
  786. BREAK    <CallInstall - hook to installable pieces>
  787.  
  788. CallInstall MACRO   name,save,restore
  789.     IFNB    <save>
  790.         SaveReg <save>
  791.     ENDIF
  792.  
  793.     push    name            ;; index of routine to call
  794.     call    Redir_Dispatcher    ;; go dispatch to redirector
  795.  
  796.     ifnb    <restore>
  797.         RestoreReg  <restore>
  798.     endif
  799. ENDM
  800.  
  801. ;   The Redir_Dispatcher routine is common low code and will
  802. ;   merely perform an indirect call through the redirector-supplied
  803. ;   address
  804.  
  805.  
  806. BREAK    <CallPCache - hook to installable PathCacher, distinct from redir.>
  807.  
  808. CallPCache MACRO name
  809.  
  810.     push    name
  811.     call    PathCache_Dispatcher
  812.  
  813.     endm
  814.  
  815. ;   The PathCache_Dispatcher is a jump-stub, which must be called far
  816. ;   because it may had off to the PathCacher, which resides in a separate
  817. ;   segment when installed.  When the PathCacher is not installed, all
  818. ;   that happens is a clear-carry and a far ret.
  819.  
  820.  
  821. BREAK <LJcc - Long Conditional Jumps>
  822.  
  823. LJE macro l
  824.  LJ JE JNE l
  825. endm
  826.  
  827. LJNE macro l
  828.  LJ jne JE l
  829. endm
  830.  
  831. LJZ macro l
  832.  LJE l
  833. endm
  834.  
  835. LJNZ macro l
  836.  LJNE l
  837. endm
  838.  
  839. LJC macro l
  840.  LJ jc JNC l
  841. endm
  842.  
  843. LJNC macro l
  844.  LJ jnc JC l
  845. endm
  846.  
  847. LJA macro l
  848.  LJ ja JNA l
  849. endm
  850.  
  851. LJNA macro l
  852.  LJ jna JA l
  853. endm
  854.  
  855. LJB macro l
  856.  LJ jb JNB l
  857. endm
  858.  
  859. LJNB macro l
  860.  LJ jnb JB l
  861. endm
  862.  
  863. LJS macro l
  864.  LJ js JNS l
  865. endm
  866.  
  867. LJNS macro l
  868.  LJ jns JS l
  869. endm
  870.  
  871. LJAE macro l
  872.  LJ jae JNAE l
  873. endm
  874.  
  875. LJBE macro l
  876.  LJ jbe JNBE l
  877. endm
  878.  
  879. LJL macro l
  880.  LJ jl JNL l
  881. endm
  882.  
  883. LJG macro l
  884.  LJ jg JNG l
  885. endm
  886.  
  887. LJLE macro l
  888.  LJ jle JNLE l
  889. endm
  890.  
  891. DLJE macro l
  892.  DLJ JE JNE l
  893. endm
  894.  
  895. DLJNE macro l
  896.  DLJ jne JE l
  897. endm
  898.  
  899. DLJZ macro l
  900.  DLJE l
  901. endm
  902.  
  903. DLJNZ macro l
  904.  DLJNE l
  905. endm
  906.  
  907. DLJC macro l
  908.  DLJ jc JNC l
  909. endm
  910.  
  911. DLJNC macro l
  912.  DLJ jnc JC l
  913. endm
  914.  
  915. DLJA macro l
  916.  DLJ ja JNA l
  917. endm
  918.  
  919. DLJNA macro l
  920.  DLJ jna JA l
  921. endm
  922.  
  923. DLJB macro l
  924.  DLJ jb JNB l
  925. endm
  926.  
  927. DLJNB macro l
  928.  DLJ jnb JB l
  929. endm
  930.  
  931. DLJS macro l
  932.  DLJ js JNS l
  933. endm
  934.  
  935. DLJNS macro l
  936.  DLJ jns JS l
  937. endm
  938.  
  939. DLJAE macro l
  940.  DLJ jae JNAE l
  941. endm
  942.  
  943. DLJBE macro l
  944.  DLJ jbe JNBE l
  945. endm
  946.  
  947. DLJG macro l
  948.  DLJ jg JNG l
  949. endm
  950.  
  951. DLJL macro l
  952.  DLJ jl JNL l
  953. endm
  954.  
  955. DLJLE macro l
  956.  DLJ jle JNLE l
  957. endm
  958.  
  959.  
  960. ;*    LJ - generate long conditional jump
  961. ;
  962. ;    if target preceeds us and is in range just use a short jump
  963. ;    else use a long jump
  964. ;
  965. ;    LJ <direct jmp>,<skip jmp>,<label>
  966.  
  967. LJ MACRO dirop,idirop,l
  968.  local a
  969.  IF ((.TYPE l) XOR 20h) AND 0A0h
  970.   idirop a                   ;; not defined or is external
  971.   jmp l
  972. a:
  973.  ELSE                       ;; is local definied
  974.   IF (($-l) LT 124) AND ($ GT l)
  975.    dirop l                  ;; is before and within range
  976.   ELSE
  977.    idirop a                  ;; is out of range or forward (pass 2)
  978.    jmp l
  979. a:
  980.   ENDIF
  981.  ENDIF
  982. ENDM
  983.  
  984.  
  985. ;*    DLJ - generate debug long conditional jump
  986. ;
  987. ;    If DEBUG is defined then we generate a long jump, else a short
  988. ;    one.
  989. ;
  990. ;    DLJ <direct jmp>,<skip jmp>,<label>
  991.  
  992. DLJ MACRO dirop,idirop,l
  993.  local a
  994.  IF Debug
  995.   idirop a
  996.   jmp l
  997. a:
  998.  ELSE
  999.   dirop l
  1000.  ENDIF
  1001. ENDM
  1002.  
  1003.  
  1004. ;*    DLJMP - generate debug long jump
  1005. ;
  1006. ;    If Debug is defined then generate long jump, else a short one.
  1007. ;
  1008. ;    DLJMP <label>
  1009.  
  1010. DLJMP macro lbl
  1011.  IF Debug
  1012.   jump lbl
  1013.  ELSE
  1014.   jmp short lbl
  1015.  ENDIF
  1016. ENDM
  1017.  
  1018.  
  1019. .xcref    LJE, LJNE, LJZ, LJNZ, LJC, LJNC, LJA, LJNA
  1020. .xcref    LJB, LJNB, LJS, LJNS, LJAE, LJBE, LJG, LJL, LJLE
  1021. .xcref    DLJE, DLJNE, DLJZ, DLJNZ, DLJC, DLJNC, DLJA, DLJNA
  1022. .xcref    DLJB, DLJNB, DLJS, DLJNS, DLJAE, DLJBE, DLJG, DLJL, DLJLE
  1023. .xcref    LJ,DLJ
  1024.  
  1025.  
  1026. BREAK <NEW MACROS FOR 4.0>
  1027.  
  1028. ReferTask MACRO sym,len
  1029.  TaskArea segment
  1030.  
  1031.  IFIDN <len>,<WORD>
  1032.  EXTRN &sym:WORD
  1033.  ELSE
  1034.  IFIDN <len>,<DWORD>
  1035.  EXTRN &sym:DWORD
  1036.  ELSE
  1037.  EXTRN &sym:BYTE
  1038.  ENDIF
  1039.  ENDIF
  1040.  
  1041.  TaskArea ENDS
  1042. ENDM
  1043.  
  1044. ReferInitGlobal MACRO sym,len
  1045.  InitData segment
  1046.  
  1047.  IFIDN <len>,<WORD>
  1048.  EXTRN &sym:WORD
  1049.  ELSE
  1050.  IFIDN <len>,<DWORD>
  1051.  EXTRN &sym:DWORD
  1052.  ELSE
  1053.  EXTRN &sym:BYTE
  1054.  ENDIF
  1055.  ENDIF
  1056.  
  1057.  InitData ENDS
  1058. ENDM
  1059.  
  1060.  
  1061. ReferGlobal MACRO sym,len
  1062.  CONSTANTS SEGMENT
  1063.  
  1064.  IFIDN <len>,<WORD>
  1065.  EXTRN &sym:WORD
  1066.  ELSE
  1067.  IFIDN <len>,<DWORD>
  1068.  EXTRN &sym:DWORD
  1069.  ELSE
  1070.  IFIDN <len>,<QWORD>
  1071.  EXTRN &sym:QWORD
  1072.  ELSE
  1073.  EXTRN &sym:BYTE
  1074.  ENDIF
  1075.  ENDIF
  1076.  ENDIF
  1077.  
  1078.  CONSTANTS ENDS
  1079. ENDM
  1080.  
  1081.  
  1082.  
  1083. ReferHighGlobal MACRO sym,symtype
  1084. HIGHDATA SEGMENT
  1085.  
  1086. EXTRN &sym:&symtype
  1087.  
  1088. HIGHDATA ENDS
  1089. ENDM
  1090.  
  1091.     ?farcode = FC_DosCode    ; default to near code
  1092.  
  1093. ;**    NEARCODE/FARCODE macros - used to control model of calls
  1094. ;    used in macros (InternalError, DBPRT, PMONLY, etc.).
  1095. ;    These macros should be invoked just *prior* to every code
  1096. ;    segment declaration, and OUTSIDE of all segments.
  1097.  
  1098. NEARCODE macro
  1099. ifdef FSSTRICT
  1100.     EXTRNFAR AssertNoBufProc
  1101. endif
  1102.     ?farcode = FC_DosCode    ; near code segment
  1103.     assume cs:DosCode
  1104. endm
  1105.  
  1106. FARCODE macro    segname,NoIntErr,NoProtReal,NoDPRINTF
  1107.     EXTRNFAR IntErr,<NoIntErr>
  1108.     EXTRNFAR IntErrNull,<NoIntErr>
  1109. ifdef MODECHECK
  1110.     EXTRNFAR TaskOnly,<NoProtReal>
  1111.     EXTRNFAR ProtTaskOnly,<NoProtReal>
  1112.     EXTRNFAR ProtOnly,<NoProtReal>
  1113.     EXTRNFAR RealTaskOnly,<NoProtReal>
  1114.     EXTRNFAR RealOnly,<NoProtReal>
  1115.     EXTRNFAR RealProcTaskOnly,<NoProtReal>
  1116. endif
  1117. if Debug
  1118.     EXTRNFAR DPRINTF,<NoDPRINTF>
  1119.     EXTRNFAR dbtest,<NoDPRINTF>
  1120. endif
  1121. ifidn    <segname>,<INIT>
  1122.     assume cs:DosInitCode
  1123.     ?farcode = FC_InitCode        ; Indicate which far code segment
  1124. else
  1125. ifidn    <segname>,<HIGH>
  1126.     assume cs:DosHighCode
  1127.     ?farcode = FC_HighCode        ; Indicate which far code segment
  1128. else
  1129. ifidn    <segname>,<HIGH2>
  1130.     assume cs:DosHigh2Code
  1131.     ?farcode = FC_High2Code     ; Indicate which far code segment
  1132. else
  1133. ifidn    <segname>,<RING3>
  1134.     assume cs:DosRing3Code
  1135.     ?farcode = FC_Ring3Code     ; Indicate which far code segment
  1136. else
  1137. ifidn    <segname>,<INITRM>
  1138.     assume cs:DosInitRMCode
  1139.     ?farcode = FC_InitRMCode    ; Indicate which far code segment
  1140. else
  1141. if2
  1142.     %out FARCODE: bad segment name: segname
  1143.     .ERR
  1144. endif
  1145. endif
  1146. endif
  1147. endif
  1148. endif
  1149. endif
  1150. ifdef FSSTRICT
  1151.     if    ?farcode ne FC_High2Code
  1152.     EXTRNFAR AssertNoBufProc
  1153.     endif
  1154. endif
  1155. endm
  1156.  
  1157.  
  1158. ;**    GENCALL - generate a call of the appropriate model
  1159. GENCALL macro    target
  1160. if ?farcode
  1161.     CALLFAR target
  1162. else
  1163.     invoke    target
  1164. endif
  1165. endm
  1166.  
  1167.  
  1168. ;**    Internal error detected in system
  1169. ;    Also used by the bios!!
  1170.  
  1171. ifndef DataOffset            ;; if not defined by bios
  1172. DataOffset equ    offset DosGroup:    ;; use DosGroup
  1173. endif
  1174.  
  1175. InternalError    macro    arg,lab
  1176. local a
  1177. if IntErrF or Debug
  1178.     push    DataOffset a
  1179.     GENCALL IntErr
  1180. else
  1181.     GENCALL IntErrNull        ;; no string passed
  1182. endif
  1183. ifdef    ?iecnt                ;; if ModName macro was invoked
  1184.     IntErrLabel %?iecnt,lab     ;; generate a public label
  1185.     ?iecnt = ?iecnt + 1        ;; and bump sequential label number
  1186. endif
  1187. if IntErrF or Debug
  1188. IntErrMsg segment
  1189. a    db    '&arg',0dh,0ah,'$'
  1190. IntErrMsg ends
  1191. endif
  1192. ENDM
  1193.  
  1194. ModName macro    mn
  1195.     ?iecnt = 0
  1196.     IntErrLabel macro n,lab
  1197.     ifnb <lab>
  1198.         public ie_&mn&&n&&_&&lab
  1199.     ie_&mn&&n&&_&&lab:
  1200.     else
  1201.         public ie_&mn&&n
  1202.     ie_&mn&&n:
  1203.     endif
  1204.     endm
  1205. endm
  1206.  
  1207. BREAK    <Stack frame manipulators>
  1208.  
  1209. LocalVar macro    name,length,lowname,highname,pad
  1210. local a
  1211.     ?pad = 0
  1212.     ?nopad = 0
  1213.     ifidn <pad>,<PAD>
  1214.     ?pad = 1
  1215.     endif
  1216.     ifidn <pad>,<NOPAD>
  1217.     ?nopad = 1
  1218.     endif
  1219.  
  1220.     ifidn <length>,<BP>        ;; makes a variable point to the old BP
  1221.     name EQU  (WORD PTR [BP])
  1222.     else
  1223.     ifidn <length>,<BYTE>
  1224.     ?frame =  ?frame + 1
  1225.     a = ?frame
  1226.     name EQU  (BYTE PTR [BP-a])
  1227.     else
  1228.     ifidn <length>,<DBYTE>
  1229.     if ?frame and 1
  1230.         ?frame = ?frame + 1
  1231.     endif
  1232.     ?frame =  ?frame + 2
  1233.     a = ?frame
  1234.     name EQU  (WORD PTR [BP-a])
  1235.     ifb <lowname>
  1236.         name&l EQU    (BYTE PTR [BP-a])
  1237.     else
  1238.         lowname EQU  (BYTE PTR [BP-a])
  1239.     endif
  1240.     ifb <highname>
  1241.         name&h EQU    (BYTE PTR [BP-a+1])
  1242.     else
  1243.         highname EQU  (BYTE PTR [BP-a+1])
  1244.     endif
  1245.     else
  1246.     ifidn <length>,<WORD>
  1247.     ife ?nopad
  1248.         if ?frame and 1
  1249.         ?frame = ?frame + 1
  1250.         endif
  1251.     endif
  1252.     ?frame =  ?frame + 2
  1253.     a = ?frame
  1254.     name EQU  (WORD PTR [BP-a])
  1255.     else
  1256.     ifidn <length>,<DWORD>
  1257.     if ?frame and 1
  1258.         ?frame = ?frame + 1
  1259.     endif
  1260.     ?frame =  ?frame + 4
  1261.     a = ?frame
  1262.     name EQU  (DWORD PTR [BP-a])
  1263.     name&l EQU  (WORD PTR [BP-a])
  1264.     name&h EQU  (WORD PTR [BP-a+2])
  1265.     else
  1266.     ?frame =  ?frame + length
  1267.     if ?pad
  1268.         if ?frame and 1
  1269.         ?frame = ?frame + 1
  1270.         endif
  1271.     endif
  1272.     a = ?frame
  1273.     name EQU  (BYTE PTR [BP-a])
  1274.     endif    ;; DWORD
  1275.     endif    ;; WORD
  1276.     endif    ;; DBYTE
  1277.     endif    ;; BYTE
  1278.     endif    ;; BP
  1279. endm
  1280.  
  1281. EnterProc   macro varlist
  1282. local a
  1283.     if ?frame and 1
  1284.     ?frame = ?frame + 1        ;; make final frame even
  1285.     endif
  1286.     if ?frame
  1287.     ifb <varlist>            ;; if no LocalVars initialized
  1288.         enter ?frame,0        ;; all done
  1289.     else
  1290.         push  bp            ;; else set up bp frame
  1291.         mov   bp,sp
  1292.         a = ?frame
  1293.         irp var,<varlist>        ;; and push each value
  1294.         if2
  1295.             ife a
  1296.             %out EnterProc: too many args
  1297.             .err
  1298.             endif
  1299.         endif
  1300.         push  var
  1301.         a = a - 2
  1302.         endm
  1303.         if a            ;; if any left over, adjust sp
  1304.         if a gt 4
  1305.             lea  sp,[bp-?frame] ;; takes 3 bytes
  1306.         else
  1307.             push  ax
  1308.             if a eq 4
  1309.             push  ax    ;; if a==4, takes 2 bytes
  1310.             endif
  1311.         endif
  1312.         endif
  1313.     endif
  1314.     else
  1315.     push bp
  1316.     mov  bp,sp
  1317.     endif
  1318. endm
  1319.  
  1320. LeaveProc   macro
  1321.     leave
  1322. endm
  1323.  
  1324. ArgVar    macro    name,length,lowname,highname
  1325. local a
  1326.     a = ?aframe + ?abase
  1327.     ifidn <length>,<BYTE>
  1328.     ?aframe =  ?aframe + 1
  1329.     name EQU  (BYTE PTR [BP+a])
  1330.     else
  1331.     ifidn <length>,<DBYTE>
  1332.     ?aframe =  ?aframe + 2
  1333.     name EQU  (WORD PTR [BP+a])
  1334.     ifb <lowname>
  1335.         name&l EQU    (BYTE PTR [BP+a])
  1336.     else
  1337.         lowname EQU  (BYTE PTR [BP+a])
  1338.     endif
  1339.     ifb <highname>
  1340.         name&h EQU    (BYTE PTR [BP+a+1])
  1341.     else
  1342.         highname EQU  (BYTE PTR [BP+a+1])
  1343.     endif
  1344.     else
  1345.     ifidn <length>,<WORD>
  1346.     ?aframe =  ?aframe + 2
  1347.     name EQU  (WORD PTR [BP+a])
  1348.     else
  1349.     ifidn <length>,<DWORD>
  1350.     ?aframe =  ?aframe + 4
  1351.     name EQU  (DWORD PTR [BP+a])
  1352.     name&l EQU  (WORD PTR [BP+a])
  1353.     name&h EQU  (WORD PTR [BP+a+2])
  1354.     else
  1355.     ?aframe =  ?aframe + length
  1356.     name EQU  (BYTE PTR [BP+a])
  1357.     endif    ;; DWORD
  1358.     endif    ;; WORD
  1359.     endif    ;; DBYTE
  1360.     endif    ;; BYTE
  1361. endm
  1362.  
  1363. BREAK    <ERRNZ - Conditional Error>
  1364.  
  1365.  
  1366. ;** ERRNZ - generate assembly error if arg != 0
  1367. ;
  1368.  
  1369. ERRNZ    MACRO    expr
  1370. .errnz    expr
  1371. ENDM
  1372.  
  1373.  
  1374.  
  1375. ;*  POPFF - special version of pop flags for i286
  1376. ;
  1377. ;   This avoids the pitfalls of the 286 POPF instruction
  1378. ;   which will sometimes allow an interrupt to come in
  1379. ;   even if IF is off in both the old and new flags.
  1380.  
  1381. POPFF    macro
  1382. local    a
  1383.     push    cs
  1384. if ?farcode
  1385.     push    offset cs:a
  1386.     iret
  1387. a:
  1388. else
  1389.     invoke    PopFlags
  1390. endif
  1391. endm
  1392.  
  1393. ;**    POPAF - pop arithmetic flags into flags register.  Avoids the
  1394. ;        popf interrupt exposure bug and is more efficient than
  1395. ;        the POPFF macro.  To be used ONLY when interrupt flag
  1396. ;        state was not modified and does not need to be restored.
  1397. ;        Requires a scratch register parameter, preferably AX.
  1398. ;
  1399. ;    If reg is AX:
  1400. ;        pop ax
  1401. ;        xchg ah,al
  1402. ;        sahf
  1403. ;    Else
  1404. ;        pop reg
  1405. ;        xchg ax,reg
  1406. ;        xchg ah,al
  1407. ;        sahf
  1408. ;        xchg reg,ax
  1409.  
  1410. POPAF    macro    reg
  1411. local ?useax
  1412.     ?useax = 0
  1413.     irp x,<ax,AX,Ax,aX>
  1414.     ifidn <x>,<reg>
  1415.         ?useax = 1
  1416.     endif
  1417.     endm
  1418.     pop    reg
  1419.     ife ?useax
  1420.     xchg    ax,reg
  1421.     endif
  1422.     mov ah,al
  1423.     sahf
  1424.     ife ?useax
  1425.     mov    ax,reg
  1426.     endif
  1427. endm
  1428.  
  1429.  
  1430. ;**    RMONLY    - verify that the processor is in real mode
  1431. RMONLY    macro    task
  1432.     RMPM    Real,<task>
  1433. endm
  1434.  
  1435.  
  1436. ;**    PMONLY    - verify that the processor is in protected mode
  1437. PMONLY    macro    task
  1438.     RMPM    Prot,<task>
  1439. endm
  1440.  
  1441.  
  1442. ;**    DUALMODE - document that the processor may be in either mode
  1443. DUALMODE macro    task
  1444.     RMPM    <>,<task>
  1445. endm
  1446.  
  1447.  
  1448. ;**    RMPROCONLY  - verify that the currently running process is the
  1449. ;              real mode process.  Presumed to be at task time.
  1450. RMPROCONLY    macro
  1451.     RMPM    RealProc,TASKTIME
  1452. endm
  1453.  
  1454.  
  1455. ;**    RMPM - RMONLY/PMONLY support
  1456. RMPM    macro    rmpm,task
  1457. ifdef MODECHECK
  1458. ifnb <task>
  1459.     if2
  1460.     ifdif <task>,<TASKTIME>
  1461.         %out RMONLY/PMONLY/DUALMODE/RMPROCONLY: bad macro arg: task
  1462.         .ERR
  1463.     endif
  1464.     endif
  1465.     ifb <rmpm>
  1466.     GENCALL TaskOnly
  1467.     else
  1468.     GENCALL rmpm&TaskOnly
  1469.     endif
  1470. else
  1471.     ifnb <rmpm>
  1472.     GENCALL rmpm&Only
  1473.     endif
  1474. endif
  1475. endif
  1476. endm
  1477.  
  1478.  
  1479. ;*  callgate - allow ring3 code in doscode call api
  1480. ;
  1481. ;   Kernel entry looks just like a normal api call
  1482.  
  1483. callgate MACRO    gate
  1484. ifndef GDT_&gate
  1485.     extrn    GDT_&gate:BYTE
  1486. endif
  1487.     db    9ah                ; far ret
  1488.     dw    0,GSEL GDT_&gate
  1489. ENDM
  1490.  
  1491.  
  1492. ;**    IODelay - delay long enough for the bus to catch up to the cpu
  1493. IODelay macro
  1494.     jmp    short $+2
  1495. endm
  1496.  
  1497.  
  1498. ;**    BEGINNOBLOCK/ENDNOBLOCK - begin/end kernel critical section.
  1499. ;    Debugging aid only, ProcBlocks and switching tasks shouldn't take
  1500. ;    place when the variable is non-zero, else an internal error will
  1501. ;    be generated.
  1502.  
  1503. ifdef MISCSTRICT
  1504.     BEGINNOBLOCK macro    segreg
  1505.     ifndef NoProcBlock
  1506.         ReferGlobal NoProcBlock,BYTE
  1507.     endif
  1508.     push    ax
  1509.     pushf
  1510.     ifb <segreg>
  1511.         push  ds
  1512.         DosContext ds,,noassume
  1513.         inc   ds:[NoProcBlock]        ;; increment counter
  1514.         pop   ds
  1515.     else
  1516.         inc   segreg:[NoProcBlock]        ;; increment counter
  1517.     endif
  1518.     POPAF    ax
  1519.     pop    ax
  1520.     endm
  1521.  
  1522.     ENDNOBLOCK macro    segreg
  1523.     ifndef NoProcBlock
  1524.         ReferGlobal NoProcBlock,BYTE
  1525.     endif
  1526.     push    ax
  1527.     pushf
  1528.     ifb <segreg>
  1529.         push  ds
  1530.         DosContext ds,,noassume
  1531.         dec   ds:[NoProcBlock]        ;; decrement counter
  1532.         pop   ds
  1533.     else
  1534.         dec   segreg:[NoProcBlock]        ;; decrement counter
  1535.     endif
  1536.     POPAF    ax
  1537.     pop    ax
  1538.     endm
  1539. else
  1540.     BEGINNOBLOCK macro
  1541.     endm
  1542.     ENDNOBLOCK macro
  1543.     endm
  1544. endif
  1545.  
  1546.  
  1547. ;;***     macro to clear FS GS regs in a 386 processor
  1548.  
  1549. ClearFSGS    macro
  1550.     local    a,b
  1551.     a label near
  1552.  
  1553. ;; at init_time, if the CPU is a 80286, the byte immediately below will
  1554. ;; be replaced with the instruction following this macro (which must be
  1555. ;; an IRET or RETF, else Internal Error will be invoked).
  1556.  
  1557.     jmp short b
  1558.     dw    0            ;; to be part of "mov ax,0" instr
  1559.  
  1560. ;; at init-time, if the CPU is a 80386,  "jmp short b" above will
  1561. ;; be replaced by the following:
  1562. ;;    "push    ax" instruction
  1563. ;;    opcode for "mov    ax,immed data"  ; not using 'xor ax,ax', we need 
  1564. ;;                       ; to preserve the flags
  1565.  
  1566.     db    8eh,0e0h        ;; mov    fs,ax
  1567.     db    8eh,0e8h        ;; mov    gs,ax
  1568.     pop    ax
  1569.     b label near
  1570.     if ((b EQ a) OR ((b-a) GT 127))
  1571.     %out **** 386 specific code: invalid code size ****
  1572.     .err
  1573.     endif
  1574.     CodeInfoTbl SEGMENT
  1575.         dd    a        ;; save the address to the code
  1576.         dw    b - a        ;; save the size of the code
  1577.     CodeInfoTbl ENDS
  1578. endm                    ;; end of macro ClearFSGS
  1579.  
  1580.  
  1581. ;**    DefTaskData - define resizable task control data structures
  1582. ;
  1583. ;    This macro is used to declare a task control data
  1584. ;    structure that can be resized after the maximum
  1585. ;    number of threads allowed in the system has been
  1586. ;    determined
  1587. ;
  1588. ;    INPUT    name        Name of pointer to structure
  1589. ;        width        Width of an element in structure
  1590. ;        length        Number of elements in structure
  1591. ;        value        Initial value for each element
  1592.  
  1593. DefTaskData    macro    name,width,length,value
  1594. local    l
  1595. CONSTANTS segment
  1596.     public    name
  1597. name    dw    offset DosGroup:l
  1598. CONSTANTS ends
  1599. LASTDATA segment
  1600.     dw    offset DosGroup:name    ;; point to pointer to this array
  1601. ifidn    <width>,<WORD>
  1602.     db    2            ;; give the width of the item
  1603. l    dw    length dup (value)     ;; reserve space for the item
  1604. else
  1605. ifidn    <width>,<BYTE>
  1606.     db    1
  1607. l    db    length dup (value)
  1608. else
  1609. ifidn    <width>,<DWORD>
  1610.     db    4
  1611. l    dd    length dup (value)
  1612. else
  1613.     db    width
  1614. l    db    length dup (width dup (value))
  1615. endif
  1616. endif
  1617. endif
  1618. LASTDATA ends
  1619. endm
  1620.  
  1621.  
  1622. ;* AssertCLD - Check the state of the direction flag
  1623. ;
  1624. ;    Entry: none
  1625. ;    Exit:  none
  1626. ;    Uses:  <reg>, Flags
  1627. ;
  1628. ;    Causes an internal error if the direction flag is set
  1629. ;
  1630. AssertCLD macro    proc, reg
  1631. local    acld
  1632. ifdef MISCSTRICT
  1633.     ifnb <reg>
  1634.     pushf
  1635.     pop    reg
  1636.     test    reg,f_Direction        ;; make sure mi.inc is included
  1637.     else
  1638.     push    ax
  1639.     pushf
  1640.     pop    ax
  1641.     test    ax,f_Direction        ;; make sure mi.inc is included
  1642.     pop    ax
  1643.     endif
  1644.     jz      acld            ;; jmp if direction flag is clear
  1645.     InternalError <&proc&: direction flag set>
  1646. acld:      
  1647. endif
  1648. endm
  1649.  
  1650.  
  1651. ;***    AssertNoBuf - Assert that current thread isn't holding a buffer
  1652. ;
  1653. ;    AssertNoBuf is used to detect certain states that often lead to
  1654. ;    deadlock.  In particular, we'll often deadlock if we call the
  1655. ;    swapper while holding a buffer.  We can call the swapper either
  1656. ;    via a call to the memory manager, or via taking a not-present
  1657. ;    fault touching a swappable segment.  AssertNoBuf should be placed
  1658. ;    anywhere we might do these things to help catch accidentally doing
  1659. ;    them with a buffer locked.
  1660. ;
  1661. ;    AssertNoBuf is turned on by the FSSTRICT flag.
  1662. ;
  1663. ;    AssertNoBuf is by no means fool-proof, but should detect the
  1664. ;    majority of cases where we have a buffer locked.
  1665. ;
  1666. ;    ENTRY    (SS) = TaskArea
  1667. ;    EXIT    None if OK, InternalError if error found
  1668. ;    USES    None, including flags
  1669.  
  1670. AssertNoBuf macro
  1671. ifdef    FSSTRICT
  1672.     if    ?farcode EQ FC_High2Code    ;; in same segment, near call
  1673.     invoke    AssertNoBufProc
  1674.     else                ;; Generate FAR call
  1675.     callfar AssertNoBufProc
  1676.     endif
  1677. endif
  1678. endm
  1679.