home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DOS / DOSINC / OSMACA.INC < prev    next >
Encoding:
Text File  |  1995-04-14  |  47.5 KB  |  1,461 lines

  1. ;*DDK*************************************************************************/
  2. ;
  3. ; COPYRIGHT    Copyright (C) 1995 IBM Corporation
  4. ;
  5. ;    The following IBM OS/2 WARP source code is provided to you solely for
  6. ;    the purpose of assisting you in your development of OS/2 WARP device
  7. ;    drivers. You may use this code in accordance with the IBM License
  8. ;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
  9. ;    Copyright statement may not be removed.;
  10. ;*****************************************************************************/
  11. ;       SCCSID = @(#)osmaca.inc 6.4 91/10/18
  12. ;***    OSMACA.INC
  13. ;
  14. ;       Macro file for OS/2 kernel
  15. ;
  16. ;       SCCSID = @(#)osmaca.inc 6.4 91/10/18
  17. ;
  18. ;       This file provides the following macros:
  19. ;
  20. ;         AsmVars
  21. ;         AsmVar
  22. ;         EXTRNFAR
  23. ;         EXTRN16
  24. ;         EXTRN32
  25. ;         EXTRNF32
  26. ;         DDFAR
  27. ;         MOVFAROFFSET
  28. ;         CALLFAR
  29. ;         CALL16
  30. ;         JMPFAR
  31. ;         JMP16
  32. ;         CALLF32
  33. ;         CCALL32
  34. ;         PCALL32
  35. ;         CALL32
  36. ;         JMP32
  37. ;         ThunkFar32
  38. ;         CallInstall
  39. ;         SegContext
  40. ;         DosContext
  41. ;         GDTContext
  42. ;         TaskContext
  43. ;         DosInitContext
  44. ;         DosMTEContext
  45. ;         FlatContext
  46. ;         NullContext
  47. ;         ReferGlobal
  48. ;         ReferGDT
  49. ;         ReferTask
  50. ;         ReferHigh2
  51. ;         ReferInitGlobal
  52. ;         ReferFlat
  53. ;         FARCODE
  54. ;         InternalError
  55. ;         Panic
  56. ;         ModName
  57. ;         BeginNoBlock
  58. ;         EndNoBlock
  59. ;         AssertCLD
  60. ;         AssertNoBuf
  61. ;         DefTaskData
  62. ;         CallGate
  63. ;         StampRPL
  64.  
  65. ; 12/15/93  RAC  76699  Make Perfview and Tracing Optional in system
  66. ; 1/4/94    RAC  77052  Add check for MMIO build to include RAS
  67.  
  68. ;***    OLD usage equates
  69.  
  70. ifndef  BREAK
  71. BREAK           equ     <Break>
  72. endif
  73.  
  74. ifndef  CpuMode
  75. CpuMode         equ     <CPUMode>
  76. endif
  77.  
  78. ;
  79. ; The RAS flag causes all RAS related code to be assembled as
  80. ; part of the DOS. All RAS related code should be surrounded
  81. ; by:
  82. ;       IF RAS
  83. ;         :
  84. ;       ras code
  85. ;         :
  86. ;       ENDIF   ; RAS
  87. ;
  88.  
  89. ; If building Perfview and tracing kernal, turn on RAS, otherwise turn it off
  90. ; D 76699.  D 77052, adds check for MMIO build.
  91. ifdef PERFVIEW
  92. RAS     EQU     1
  93. else
  94. ifdef MMIOPH
  95. RAS     EQU     1
  96. else
  97. RAS     EQU     0
  98. endif   ; MMIOPH
  99. endif   ; PERFVIEW
  100.  
  101. ;***    AsmVars - initialize variables
  102. ;
  103. ;       Each variable in varlist is examined to see if it has already
  104. ;       been defined. If so, nothing happens. Otherwise it is
  105. ;       defined with the value "value".
  106. ;
  107. ;       ENTRY:  varlist = list of variables enclosed in < >
  108. ;               value   = a value to assign to all undefined variables.
  109. ;
  110. ;       EXIT:   undefined variables in varlist are set to "value."
  111.  
  112. AsmVars macro   varlist, value
  113.     irp var,<varlist>
  114.         AsmVar var, value
  115.     endm
  116. endm
  117.  
  118. ;***    AsmVar - initialize a variable
  119. ;
  120. ;       The variable "var" is examined to see if it has already
  121. ;       been defined. If so, nothing happens. Otherwise it is
  122. ;       defined with the value "value."
  123. ;
  124. ;       ENTRY:  var   = a variable
  125. ;               value = value to assign to var
  126. ;
  127. ;       EXIT:   var is set to "value" if it wasn't previously defined.
  128.  
  129. AsmVar  macro   var, value
  130.     ifndef var
  131.         ifb <value>
  132.             var = FALSE
  133.         else
  134.             var = value
  135.         endif
  136.     endif
  137. endm
  138.  
  139. ;       Check if all (or most) the checking flags are to be enabled.
  140.  
  141. ifdef ALLSTRICT
  142.     AsmVar DEMSTRICT,  TRUE
  143.     AsmVar EM86STRICT, TRUE
  144.     AsmVar VDHSTRICT,  TRUE
  145.     AsmVar VDDSTRICT,  TRUE
  146.     AsmVar VDMMSTRICT, TRUE
  147.     AsmVar DEVSTRICT,  TRUE
  148.     AsmVar FSSTRICT,   TRUE
  149.     AsmVar PIPESTRICT, TRUE
  150.     AsmVar INFOSTRICT, TRUE
  151.     AsmVar INTERRPRT,  TRUE
  152.     AsmVar KMSTRICT,   TRUE
  153.     AsmVar LDRSTRICT,  TRUE
  154.     AsmVar MISCSTRICT, TRUE
  155.     AsmVar MODECHECK,  TRUE
  156.     AsmVar PERFSTRICT, TRUE
  157.     AsmVar PGSTRICT,   TRUE
  158.     AsmVar SELSTRICT,  TRUE
  159.     AsmVar SEMSTRICT,  TRUE
  160.     AsmVar SMSTRICT,   TRUE
  161.     AsmVar VMSTRICT,   TRUE
  162.     AsmVar VOLPTRCHK,  TRUE
  163.     AsmVar ALIGNCODE,  TRUE
  164.     AsmVar DBGSTRICT,  TRUE
  165.     AsmVar PTSTRICT,   TRUE
  166. endif
  167.  
  168. ifdef INTERRPRT
  169.         IntErrF = TRUE  ; for v86code only
  170. else
  171.         IntErrF = FALSE ; for v86code only
  172. endif
  173.  
  174. AsmVars <Debug,ShareF>
  175.  
  176. ?om1 = 0                ;; osmaca.inc scratch variable
  177.  
  178. ;***    ?GenCall - generate a call to a hybrid procedure
  179. ;
  180. ;       It generates either far call or near call depending on the
  181. ;       last use of the FARCODE macro.
  182. ;
  183. ;       ENTRY:  target = name of hybrid procedure
  184. ;               targetseg = SN_targetseg of target segment
  185. ;       (global variables)
  186. ;               ?farcode = <targetseg> - generate appropriate type call
  187. ;
  188. ;       EXIT:   code generated to call the hybrid procedure
  189. ;
  190. ;       SEE ALSO: Procedure
  191.  
  192. ?GenCall macro  target, targetseg
  193.     if (?farcode eq targetseg)          ;; source and target in same segment?
  194.         if2
  195.             ifndef target
  196.                 extrn target:near
  197.             endif
  198.         endif
  199.         call  target                    ;; near 16 or 32 bit call
  200.     elseif (?cstype eq ?CS_32bit)       ;; source in 32 bit segment?
  201.         CALL16 target                   ;; far 32 bit call
  202.     elseif (targetseg eq SN_DosHigh32Code) ;; target in 32 bit segment?
  203.         if2
  204.             ifndef target
  205.                 extrn target:near
  206.             endif
  207.         endif
  208.         CALL32 target                   ;; near 32 bit call (with thunk)
  209.     else                                ;; else source & target in 16 bit segs
  210.         CALLFAR target                  ;; far 16 bit call
  211.     endif
  212. endm
  213.  
  214.  
  215. ;***    EXTRNFAR - generate an extrn for the hybrid symbol.
  216. ;***    EXTRN16 - generate an extrn for the far16 symbol.
  217. ;***    EXTRN32 - generate an extrn for the near 32 bit symbol.
  218. ;***    EXTRNF32 - generate an extrn for the far32 symbol.
  219. ;       Skip it has already been defined or the skip argument is nonblank.
  220. ;
  221. ;       ENTRY   name = symbol
  222. ;               skip = blank - generate the extrn
  223. ;                    = non-blank - don't generate the extrn
  224. ;       EXIT    an extrn generated if skip is blank.
  225. ;       SEE ALSO Procedure
  226.  
  227. EXTRNFAR macro  name, skip
  228.     if2
  229.         ?GenExtrn %HYBPRE_, name,, far, skip
  230.     endif
  231. endm
  232.  
  233. EXTRN16 macro name, skip
  234.     ?GenExtrn %F16PRE_, name,, far, skip
  235. endm
  236.  
  237. EXTRN32 macro name, skip
  238.     ?GenExtrn , name, fflat, near, skip
  239. endm
  240.  
  241. EXTRNF32 macro name, skip
  242.     .386p
  243.     ?GenExtrn %F32PRE_, name, fflat, far, skip
  244.     CpuMode reset
  245. endm
  246.  
  247. ?GenExtrn macro prefix, name, fflat, distance, skip
  248.     ifb <skip>
  249.         ifndef prefix&name
  250.             ifnb <fflat>
  251.                 if (?cstype ne ?CS_32bit)
  252.                     _TEXT segment
  253.                 endif
  254.             endif
  255.             .lall
  256.             extrn prefix&name:distance
  257.             .xall
  258.             ifnb <fflat>
  259.                 if (?cstype ne ?CS_32bit)
  260.                     _TEXT ends
  261.                 endif
  262.             endif
  263.         endif
  264.     endif
  265. endm
  266.  
  267.  
  268. ;***    DDFAR - generate far pointer to hybrid procedure
  269. ;***    DDOFF16 - generate 32 bit offset of far16 procedure
  270. ;***    DWOFF16 - generate 16 bit offset of far16 procedure
  271. ;
  272. ;       ENTRY:  name = name of hybrid/far16 procedure.
  273. ;                      Must be defined in the current file.
  274. ;
  275. ;       EXIT:   double word generated containing the far pointer (seg, off),
  276. ;               double word generated containing the 32 bit offset,
  277. ;               OR word generated containing the 16 bit offset.
  278. ;
  279. ;       SEE ALSO: Procedure
  280.  
  281. DDFAR   macro name
  282.     CatPrefix <dw offset>, %HYBPRE_, <name>
  283.     CatPrefix <dw seg>, %HYBPRE_, <name>
  284. endm
  285.  
  286. DDOFF16   macro name
  287.     CatPrefix <dd offset>, %F16PRE_, <name>
  288. endm
  289.  
  290. DWOFF16   macro name
  291.     CatPrefix <dw offset>, %F16PRE_, <name>
  292. endm
  293.  
  294. ;***    MOVFAROFFSET - move the offset of the far entry of a hybrid or
  295. ;                      a faronly procedure into a register or memory.
  296. ;
  297. ;       The offset is relative to the current group/segment cs is
  298. ;       assuming or relative to the supplied segment/group name.
  299. ;
  300. ;       ENTRY:  target = register or memory to receive the offset.
  301. ;               name   = hybrid/faronly procedure name
  302. ;               group  = blank - use whatever group cs is assuming
  303. ;                      = non-blank - use this as the group/segment to
  304. ;                                    calculate the offset.
  305. ;
  306. ;       EXIT:   "mov" instruction generated to move an offset into the
  307. ;               target.
  308.  
  309. MOVFAROFFSET macro target,name,group
  310.     ifb <group>
  311.         CatPrefix <mov target, offset cs:>, %HYBPRE_, <name>
  312.     else
  313.         CatPrefix <mov target, offset group:>, %HYBPRE_, <name>
  314.     endif
  315. endm
  316.  
  317. ;***    CALLFAR - generate a far16 call to a faronly/hybrid procedure
  318. ;***    CALL16 - generate a far32 call to a far16 procedure
  319. ;***    JMPFAR - generate a far16 jump to a faronly/hybrid procedure
  320. ;***    JMP16 - generate a far32 jump to a far16 procedure
  321. ;
  322. ;       The procedure must already be defined in the current file
  323. ;       in a Procedure declaration or via EXTRNFAR or EXTRN16.
  324. ;
  325. ;       ENTRY   name = name of hybrid/faronly/far16 procedure
  326. ;       EXIT    generated a far call to the given procedure
  327. ;       SEE ALSO Procedure
  328.  
  329. CALLFAR macro   name                    ;; call far16 ptr HYBPRE_&name
  330.     if2
  331.         if ?cstype eq ?CS_32bit
  332.             ProcError <CALLFAR name in 32 bit code>
  333.             .err
  334.         endif
  335.         ifdef SN_DosInitR3Code
  336.             if ?farcode eq SN_DosInitR3Code
  337.                 ProcError <CALLFAR name in ring 3 code>
  338.                 .err
  339.             endif
  340.         endif
  341.     endif
  342.     CatPrefix <call far ptr>, %HYBPRE_, <name>
  343. endm
  344.  
  345. CALL16  macro   name                    ;; call far32 ptr F16PRE_&name
  346.     if2
  347.         if (?cstype ne ?CS_32bit)
  348.             ProcError <CALL16 name in 16 bit code>
  349.             .err
  350.         endif
  351.     endif
  352.     assume cs:DOSHIGH32CODE             ;; disable assume cs:FLAT
  353.     ;;  can't use a plain far call because masm turns it into a 16 bit far call
  354.     ;;  call  far ptr %F16PRE_&name
  355.     db  MI_LONG_CALL
  356.     CatPrefix <df>, %F16PRE_, <name>
  357.     ?ASSUMECS
  358. endm
  359.  
  360. JMPFAR  macro   name
  361.     if2
  362.         if ?cstype eq ?CS_32bit
  363.             ProcError <JMPFAR name in 32 bit code>
  364.             .err
  365.         endif
  366.         ifdef SN_DosInitR3Code
  367.             if ?farcode eq SN_DosInitR3Code
  368.                 ProcError <JMPFAR name in ring 3 code>
  369.                 .err
  370.             endif
  371.         endif
  372.     endif
  373.     CatPrefix <jmp far ptr>, %HYBPRE_, <name>
  374. endm
  375.  
  376. JMP16   macro   name                    ;; jmp far ptr F16PRE_&name
  377.     if2
  378.         if (?cstype ne ?CS_32bit)
  379.             ProcError <JMP16 name in 16 bit code>
  380.             .err
  381.         endif
  382.     endif
  383.     assume cs:DOSHIGH32CODE             ;; disable assume cs:FLAT
  384.     ;; CatPrefix <jmp far ptr>, %F16PRE_, <name>
  385.     ;; use explicit opcodes to avoid masm 5 trailing nop
  386.         db      MI_OPERANDSIZE, MI_LONG_JMP
  387.         CatPrefix <dw offset>, %F16PRE_, <name>
  388.         CatPrefix <dw seg>, %F16PRE_, <name>
  389.     ?ASSUMECS
  390. endm
  391.  
  392. ;***    CCALL32 - call 32-bit near "C" procedure from a 16-bit segment
  393. ;***    CALLF32 - call 32-bit far "C" procedure from a 16-bit segment
  394. ;***    PCALL32 - call 32-bit near "PASCAL" procedure from a 16-bit segment
  395. ;***    CALL32 - call 32-bit procedure from a 16-bit segment
  396. ;***    JMP32 - jump to 32-bit procedure from a 16-bit segment
  397. ;
  398. ;       This macro calls or jumps to a 32-bit procedure from a 16-bit
  399. ;       code segment.  If requested (CALL32 only), it sets DS and ES
  400. ;       to the flat ring 0 data selector before calling the function.
  401. ;
  402. ;       CCALL32 target, [<args>], [<segargs>]
  403. ;       CALLF32 target, [<args>], [<segargs>], [CCall modifiers]
  404. ;       PCALL32 target, [<args>], [<segargs>]
  405. ;       CALL32  target, [<segargs>], [calltype], [args], [CCall modifiers]
  406. ;
  407. ;       ENTRY   target  - name of function to call
  408. ;               args    - list of argument parameters
  409. ;               segargs - optional parameter
  410. ;                         nocheck: suppress verification of DS and ES
  411. ;                         nosegcheck: suppress verification thunk seg
  412. ;                         nofar32: suppress far32 call
  413. ;                         far32: use far32 call
  414. ;                         nocall: use far jmp thunk (preserve SP for call)
  415. ;                         noalignesp: suppress alignment of esp
  416. ;                         tgtseg: causes thunk to be placed in tgtseg
  417. ;       EXIT    As from called function
  418. ;       USES    EAX, ECX, EDX (optionally DS, ES), Flags
  419.  
  420. ?thcnt = 0
  421. ?Call32Label macro modname, n, lab
  422. ;   public modname&n&lab   Defect 61299 workaround. Paul.
  423.     modname&n&lab:
  424. endm
  425.  
  426. CALLF32 macro   target, args, segargs, testarg
  427.     CALL32 <target>,<far32,segargs>,,<args>,,<testarg>
  428. endm
  429.  
  430. CCALL32 macro   target, args, segargs, modifiers, testarg
  431.     CALL32 <target>,<segargs>,<CCall>,<args>,<modifiers>,<testarg>
  432. endm
  433.  
  434. PCALL32 macro   target, args, segargs, testarg
  435.     CALL32 <target>,<segargs>,<PCall>,<args>,,<testarg>
  436. endm
  437.  
  438. ?S_NOCHECK      equ     01h     ;; <nocheck> - suppress AssertDSESFlat
  439. ?S_NOSEGCHECK   equ     02h     ;; <nosegcheck> - suppress far32 address check
  440. ?S_NOFAR32      equ     04h     ;; <nofar32> - suppress far32 call
  441. ?S_FAR32        equ     08h     ;; <far32> - use far32 call
  442. ?S_NOCALL       equ     10h     ;; <nocall> - suppress near thunk call
  443. ?S_NOALIGNESP   equ     20h     ;; <noalignesp> - suppress align esp
  444. ?S_SEG          equ     40h     ;; <???> - specify thunk segment name
  445. ?thunkcodeseg   equ     <.err>
  446.  
  447. CALL32  macro   target, segargs, calltype, args, modifiers, testarg
  448. local   label32, label16
  449.     .386p
  450.     ?sflags = 0                 ;; assert ds/es FLAT, resident thunk with retfd
  451.     ?thunkcodeseg catstr ?ThunkSeg
  452.     irp x,<segargs>                             ;; examine segargs
  453.         ifnb <x>
  454.             ifidn <x>,<nocheck>
  455.                 ?sflags = ?sflags or ?S_NOCHECK ;; don't assert ds,es FLAT
  456.             elseifidn <x>,<nosegcheck>
  457.                 ?sflags = ?sflags or ?S_NOSEGCHECK;; don't assert thunk seg
  458.             elseifidn <x>,<nofar32>
  459.                 ?sflags = ?sflags or ?S_NOFAR32 ;; don't call F32PRE_&target
  460.             elseifidn <x>,<far32>
  461.                 ?sflags = ?sflags or ?S_FAR32   ;; use call F32PRE_&target
  462.             elseifidn <x>,<nocall>
  463.                 ?sflags = ?sflags or ?S_NOCALL  ;; use jmp32/jmp16
  464.             elseifidn <x>,<noalignesp>
  465.                 ?sflags = ?sflags or ?S_NOALIGNESP ;; don't align esp
  466.             else
  467.                 ?sflags = ?sflags or ?S_SEG     ;; use specified segment
  468.                 ?thunkcodeseg catstr x
  469.             endif
  470.         endif
  471.     endm
  472.     irp x,<modifiers>                           ;; examine modifiers
  473.         ifidn <x>,<PushP>
  474.            if (?sflags and ?S_FAR32)
  475.               ProcError <CCALL32 target: PushP conflicts with call>
  476.            endif
  477.            if ((?sflags and ?S_NOALIGNESP) eq 0)
  478.                ?sflags = ?sflags or ?S_NOALIGNESP
  479.            endif
  480.            ?sflags = ?sflags or ?S_NOCALL       ;; don't use retfd
  481.         endif
  482.     endm
  483.     .lall
  484.     ?om1 = ?sflags                              ;; only for listing files
  485.     .xall
  486.     if2
  487.         ifdef SN_DosInitR3Code
  488.             if ?farcode eq SN_DosInitR3Code
  489.                 ProcError <CCALL32 target in ring 3 code>
  490.                 .err
  491.             endif
  492.         endif
  493.         ?om1 = ?sflags and (?S_FAR32 or ?S_NOFAR32 or ?S_NOCALL)
  494.         if (?om1 and (?om1 - 1))                ;; verify only one bit set
  495.             ProcError <CCALL32 target: nofar32/far32/nocall conflict>
  496.         endif
  497.         if ((?sflags and ?S_FAR32) eq 0)
  498.             ifb <calltype>
  499.                 ifnb <args>
  500.                     ProcError <CALL32 target: use CCALL32/CALLF32 with parms>
  501.                 endif
  502.                 ifnb <modifiers>
  503.                     ProcError <CALL32 target: use CCALL32/CALLF32 with CCall_modifiers>
  504.                 endif
  505.             endif
  506.         endif
  507.         ifnb <testarg>
  508.             ProcError <CCALL32 target: too many args: testarg>
  509.         endif
  510.     endif
  511.     if ((?cstype eq ?CS_32bit) eq 0)
  512.         if ((?sflags and (?S_FAR32 or ?S_NOFAR32 or ?S_NOCALL)) eq 0)
  513.             ifb <args>
  514.                 ?sflags = ?sflags or ?S_FAR32
  515.             endif
  516.         endif
  517.         if ((?sflags and ?S_FAR32) eq 0)        ;; thunk required?
  518. %           ?Eval ?thunkcodeseg <segment>       ;; put thunk in 32 bit code
  519.                 assume cs:FLAT                  ;; change to flat cs
  520.                 ?Call32Label %@FileName, %?thcnt, target
  521.                 ?thcnt = ?thcnt + 1
  522.                 label32 label near
  523. %           ?Eval ?thunkcodeseg <ends>
  524.             ?ASSUMECS                           ;; back to original cs
  525.  
  526.             if (?sflags and ?S_NOCALL)
  527.                 JMP32  label32                  ;; generate a 32-bit far jump
  528.                 .386p
  529.             else
  530.                 call  far ptr FLAT:label32      ;; generate a 32-bit far call
  531.             endif
  532.  
  533.             label16 label far                   ;; and label for return jump
  534. %           ?Eval ?thunkcodeseg <segment>       ;; put thunk in 32 bit code
  535.                 assume cs:FLAT                  ;; change to flat cs
  536.         endif
  537.     else
  538.        ?sflags = ?sflags or ?S_NOALIGNESP ;; don't align esp
  539.     endif
  540.     if ((?sflags and ?S_NOALIGNESP) eq 0)       ;; align esp?
  541. ;       push    ebp
  542. ;       lea     ebp,4[esp]
  543. ;       and     esp,not 3
  544. ;       push    ebp
  545. ;       mov     ebp,ss:-4[ebp]
  546.     endif
  547.     if ((?cstype eq ?CS_32bit) eq 0)
  548.         if ((?sflags and ?S_FAR32) eq 0)        ;; thunk required?
  549.             ?ThunkStrict %?sflags,, label16,, target
  550.         endif
  551.     endif
  552.  
  553.     if (?sflags and ?S_FAR32)                   ;; 32-bit far global thunk?
  554.         CCall <target>,<args>,<far32,modifiers> ;; make 32 bit near call
  555.     elseifnb <calltype>
  556.         calltype <target>,<args>,<modifiers>    ;; make 32 bit near call
  557.     else
  558.         call  target                            ;; make 32-bit near call
  559.     endif
  560.     if ((?sflags and ?S_NOALIGNESP) eq 0)       ;; was esp aligned?
  561. ;       pop     esp
  562.     endif
  563.  
  564.     if ((?cstype eq ?CS_32bit) eq 0)
  565.         if ((?sflags and ?S_FAR32) eq 0)
  566.             if (?sflags and ?S_NOCALL)          ;; if should use jmp
  567.                 ;; jmp far ptr label16          ;; jmp far 16:16 back to caller
  568.                 ;; use explicit opcodes to avoid masm 5 trailing nop
  569.                 db      MI_OPERANDSIZE, MI_LONG_JMP
  570.                 dw      offset label16, seg label16
  571.             else
  572.                 retf                            ;; retfd back to caller
  573.             endif
  574. %           ?Eval ?thunkcodeseg <ends>
  575.  
  576.             ?ASSUMECS                           ;; back to original cs
  577.         endif
  578.     endif
  579.     CpuMode reset                               ;; back to original cpu mode
  580. endm
  581.  
  582. JMP32   macro   name                            ;; jmp far ptr FLAT:name
  583.     if2
  584.         if (?cstype eq ?CS_32bit)
  585.             ProcError <JMP32 name from 32 bit segment>
  586.             .err
  587.         endif
  588.     endif
  589.     .386p
  590.     jmp   far ptr FLAT:name
  591.     CpuMode reset                               ;; back to original cpu mode
  592. endm
  593.  
  594. ThunkFar32 macro name, lcl, segname, fnocheck
  595.     if2
  596.         ifnb <fnocheck>
  597.             ifdif <fnocheck>,<nocheck>
  598.                 %out <ThunkFar32: bad nocheck arg: fnocheck>
  599.                 .err
  600.             endif
  601.         endif
  602.     endif
  603.     FARCODE HIGH32
  604.     segname segment
  605.     if2
  606.         ifndef name
  607.             extrn name:near
  608.         endif
  609.     endif
  610.     GenFar32 name, lcl, <usecall>, <tolabel>
  611.     ifnb <fnocheck>
  612.         ?ThunkStrict ?S_NOCHECK, %F32PRE_, name,, name
  613.     else
  614.         ?ThunkStrict 0, %F32PRE_, name,, name
  615.     endif
  616.     GenFar32 name, lcl, <usecall>, <afterlabel>
  617.     segname ends
  618. endm
  619.  
  620.  
  621. ?ThunkStrict macro sflags, srcpre, srclabel, tgtpre, tgtlabel
  622.     ifdef MISCSTRICT
  623.         if ((sflags and ?S_NOCHECK) eq 0)
  624.             ?GenCall _AssertDSESFlat, ?farcode ;; force near call
  625.         endif
  626.         if ((sflags and ?S_NOSEGCHECK) eq 0)
  627.             THUNKINIT_DATA segment
  628.                 dd  offset FLAT:srcpre&srclabel ;; source address
  629.                 dd  offset FLAT:tgtpre&tgtlabel ;; target address
  630.             THUNKINIT_DATA ends
  631.         endif
  632.     endif
  633. endm
  634.  
  635. ;***    SaveAlignESP - Save and Align ESP
  636. ;
  637. ;       Save Current ESP and Align it
  638. SaveAlignESP macro ereg
  639.     ifnb    <ereg>
  640.       mov   ereg,esp
  641.       and   esp,not 3
  642.       push  ereg
  643.     else
  644.       mov   eax,esp
  645.       and   esp,not 3
  646.       push  eax
  647.     endif
  648. endm
  649.  
  650. ;***    SegContext - load segment register(s)
  651. ;
  652. ;       Make all given segment registers point to "base".
  653. ;
  654. ;       ENTRY:  srl      = segment registers list in < >
  655. ;               gr       = general register to speed operation
  656. ;                        = blank - use slow way of loading registers
  657. ;               noassume = blank - generate an assume sr:grpnam for
  658. ;                                  each segment register sr
  659. ;                        = non-blank - don't generate assumes.
  660. ;               base     = value to be loaded into segment register(s)
  661. ;               grpnam   = name of group/segment to assume
  662. ;
  663. ;       EXIT:   code generated to load segment registers. If "gr" is
  664. ;               supplied, its content is lost.
  665. ;
  666. ;       SEE ALSO: TaskContext, DosHighContext, DosInitContext.
  667.  
  668. ?smov   macro a1, a2
  669.     mov   a1,a2
  670. endm
  671.  
  672. SegContext macro    srl,gr,noassume,base,grpnam
  673. local i
  674.     ifnb <gr>                           ;; if intermediate general register
  675.         ?gr1 equ <gr>                   ;; assume 16 bit gr
  676.         irp r,<ax,bx,cx,dx,si,di>
  677.             ifidni <e&&r&&>,<gr>
  678.                 ?gr1 equ <r>            ;; oops, load selector into 16 bit gr
  679.                 exitm
  680.             endif
  681.         endm
  682.         if (?cstype eq ?CS_32bit)
  683.             ?gr2 catstr <e>,?gr1        ;; load sr from 32 bit gr
  684.         else
  685.             ?gr2 catstr <>,?gr1         ;; load sr from 16 bit gr
  686.         endif
  687.         ?smov   %?gr1,<base>            ;; load selector into 16 bit gr
  688.         irp sr,<srl>
  689.             ?smov   sr,%?gr2            ;; load sr from native size gr
  690.         endm
  691.     else
  692.         irp sr,<srl>                    ;; for sr = *first* segreg in list
  693.             i = 0
  694.             irp r,<srl>                 ;; for r = each segreg in list
  695.                 i = i + 1
  696.                 if (i eq 1)             ;; if r is first in list
  697.                     push  base
  698.                 else                    ;; else r is second (or later) in list
  699.                     push  sr            ;; and sr contains desired value
  700.                 endif
  701.                 pop     r
  702.             endm
  703.             exitm                       ;; quit after sr = first in list
  704.         endm
  705.     endif
  706.     ifb <noassume>
  707.         irp sr,<srl>
  708.             .lall
  709.             assume sr:grpnam
  710.             .xall
  711.         endm
  712.     endif
  713. endm
  714.  
  715. ;***    DosContext - make segment register(s) point to DOSGROUP
  716. ;***    DosHighContext - make segment register(s) point to DOSHIGHDATA
  717. ;***    GDTContext - make segment register(s) point to DOSGDTDATA
  718. ;***    TaskContext - make segment register(s) point to SS; SS must be TASKAREA
  719. ;***    DosInitContext - make segment register(s) point to DOSINITDATA
  720. ;***    DosMTEContext - make segment register(s) point to DOSMTE
  721. ;***    FlatContext - make segment register(s) point to FLAT descriptor
  722. ;***    NullContext - make segment register(s) point to nothing
  723. ;
  724. ;       Loads all given segment registers with the specified group.
  725. ;       This is often used to set up DS in order to use a global DOS variable.
  726. ;
  727. ;       ENTRY:  srl      = segment registers list in < >
  728. ;               gr       = general register to speed operation
  729. ;                        = blank - use slow way of loading registers
  730. ;               noassume = blank - generate an assume sr:DOSGROUP for
  731. ;                                  each segment register sr in "srl".
  732. ;                        = non-blank - don't generate assumes.
  733. ;       (global variables)
  734. ;               groups defined in dosseg.inc
  735. ;
  736. ;       EXIT:   code generated to load segment registers. If "gr" is
  737. ;               supplied, its content is lost.
  738. ;
  739. ;       SEE ALSO: SegContext
  740.  
  741. DosContext macro    srl,gr,noassume
  742.         SegContext <srl>,gr,noassume,DOSGROUP,DOSGROUP
  743. endm
  744.  
  745. DosHighContext macro   srl,gr,noassume
  746.         SegContext <srl>,gr,noassume,DOSHIGHDATA,DOSHIGHDATA
  747. endm
  748.  
  749. GDTContext macro   srl,gr,noassume
  750.         SegContext <srl>,gr,noassume,DOSGDTDATA,DOSGDTDATA
  751. endm
  752.  
  753. TaskContext macro   srl,gr,noassume
  754.         SegContext <srl>,gr,noassume,SS,TASKAREA
  755. endm
  756.  
  757. DosInitContext macro   srl,gr,noassume
  758.         SegContext <srl>,gr,noassume,DOSINITDATA,DOSINITDATA
  759. endm
  760.  
  761. DosMTEContext   macro   srl,gr,noassume
  762.         SegContext <srl>,gr,noassume,DOSMTE,DOSMTE
  763. endm
  764.  
  765. FlatContext macro   srl,gr,noassume
  766.         SegContext <srl>,gr,noassume,<seg FLAT:DGROUP>,FLAT
  767. endm
  768.  
  769. NullContext macro   srl,gr,noassume
  770.         SegContext <srl>,gr,noassume,0,NOTHING
  771. endm
  772.  
  773. ;***    ReferGlobal - declare external symbol in DOSGROUP.
  774. ;***    ReferGDT - declare external symbol in the DOSGDTDATA.
  775. ;***    ReferTask - declare external symbol in TASKGROUP.
  776. ;***    ReferHigh2 - declare external symbol in DOSHIGH2CODE.
  777. ;***    ReferInitGlobal - declare external symbol in DOSINITDATA.
  778. ;***    ReferFlat - Declare an external symbol in FLAT group.
  779. ;
  780. ;       Declares a symbol as an external symbol in the appropriate segment.
  781. ;
  782. ;       ENTRY   sym = symbol name
  783. ;               symtype = valid masm type
  784. ;                       = blank implies byte
  785. ;                         BUGBUG: ReferTask allows obsolete symtype values
  786. ;       (global variables)
  787. ;               segments defined in dosseg.inc
  788. ;
  789. ;       EXIT    extrn generated for the symbol.
  790.  
  791. ReferGlobal macro sym, symtype, ifundef
  792.     ?refer CONSTANTS, sym, symtype, ifundef
  793. endm
  794.  
  795. ReferGDT macro sym, symtype, ifundef
  796.     ?refer GDTSTART, sym, symtype, ifundef
  797. endm
  798.  
  799. ReferTask macro sym, symtype, ifundef, nocheck
  800. local a
  801.     ifb <nocheck>
  802.         ifdef   TKOPTDA
  803.             %out ReferTask: not compatable with tkptda.inc
  804.             .err
  805.         endif
  806.     endif
  807.  
  808.     ifnb <symtype>
  809.         a = 0
  810.         irp x, <83, 128, MAXMETANAME, MAXPATHLEN, PMPATHLEN, SRCHBUFSIZE>
  811.             ifidn <symtype>, <x>        ; Is symtype a known obsolete value?
  812.                 a = 1
  813.                 exitm
  814.             endif
  815.         endm
  816.     else
  817.         a = 1
  818.     endif
  819.     if a
  820.         ?refer TASKDATA, sym, byte, ifundef
  821.     else
  822.         ?refer TASKDATA, sym, symtype, ifundef
  823.     endif
  824. endm
  825.  
  826. ReferHigh2 macro sym, symtype, ifundef
  827.     ?refer HIGH2CODE, sym, symtype, ifundef
  828. endm
  829.  
  830.  
  831. ReferInitGlobal macro sym, symtype, ifundef
  832.     ?refer INITDATA, sym, symtype, ifundef
  833. endm
  834.  
  835. ReferFlat macro sym, symtype, ifundef
  836.     .386p
  837.     ?refer _DATA, sym, symtype, ifundef
  838.     CpuMode reset
  839. endm
  840.  
  841. ?refer macro segname, sym, symtype, ifundef
  842. ifnb <ifundef>
  843.     if2
  844.         ifndef sym
  845.             segname segment
  846.             ifb <symtype>
  847.                 .lall
  848.                 extrn sym:byte
  849.                 .xall
  850.             else
  851.                 .lall
  852.                 extrn sym:symtype
  853.                 .xall
  854.             endif
  855.             segname ends
  856.         endif
  857.     endif
  858. else
  859.     segname segment
  860.     ifb <symtype>
  861.         .lall
  862.         extrn sym:byte
  863.         .xall
  864.     else
  865.         .lall
  866.         extrn sym:symtype
  867.         .xall
  868.     endif
  869.     segname ends
  870. endif
  871. endm
  872.  
  873. ifndef  SN_DosCode
  874. ;       We need SN_DosCode to be defined to compare against ?farcode.
  875. ;       dosseg.inc may never be included after dosmac.inc, if used at all.
  876.         SN_DosCode       equ    0       ; meaningless, non-redefinable value
  877. endif
  878.         ?farcode = SN_DosCode   ; default to near code
  879.  
  880. ;***    FARCODE - Introduce high DOS code segment
  881. ;
  882. ;       Tell macros that generates hybrid procedure call's to generate
  883. ;       far call's. (E.g. InternalError, DBPRT, PMONLY) This remains
  884. ;       in effect until FARCODE is invoked again. This should be invoked
  885. ;       just prior to every code segment declaration, and outside of all
  886. ;       segments. If FARCODE is not invoked, the default is "FARCODE LOW".
  887. ;
  888. ;       ENTRY:  segname    = "LOW"    - select the DOSCODE group
  889. ;                          = "INIT"   - select the DOSCODE group
  890. ;                          = "INITR3" - select the DOSINITR3CODE group
  891. ;                          = "HIGH2"  - select the DOSHIGH2CODE group
  892. ;                          = "HIGH3"  - select the DOSHIGH3CODE group
  893. ;                          = "HIGH4"  - select the DOSHIGH4CODE group
  894. ;                          = "HIGH32" - select the DOSHIGH32CODE group
  895. ;               NoPanic    = blank - generate extrn's for the Panic
  896. ;                              and InternalError macro support routines,
  897. ;                              if they haven't been defined yet
  898. ;                          = non-blank - don't generate extrn's for
  899. ;                              IntErr and IntErrNull
  900. ;               NoProtReal = blank - generate extrn's for the mode
  901. ;                              checking routines (see RMONLY, PMONLY)
  902. ;                              if they haven't been defined yet and
  903. ;                              MODECHECK is defined.
  904. ;                          = non-blank - don't generate extrn's for
  905. ;                              the mode checking routines.
  906. ;               NoDPRINTF  = blank - generate extern's for DPRINTF and
  907. ;                              dbtest if they haven't been defined yet
  908. ;                              and Debug is non-zero.
  909. ;                          = non-blank - don't generate extrn's for
  910. ;                              DPRINTF and dbtest.
  911. ;       (global variables)
  912. ;               DOSCODE   = group defined in dosseg.inc
  913. ;               MODECHECK = flag to enable the mode checking routines
  914. ;               Debug     = flag to control the DPRINTF and dbtest
  915. ;                           routines.
  916. ;
  917. ;       EXIT:   an assume cs: generated with the proper group name
  918. ;               extrn's generated for debugging/mode-checking routines.
  919. ;       (global variables)
  920. ;               ?farcode = set to SN_xxx to remember which group was selected.
  921. ;               ?cstype = set to ?CS_16bit or ?CS_32bit, according to the
  922. ;                       D bit setting for the new CS
  923.  
  924. .386p
  925.     assume fs:FLAT                      ;; to enable the FLAT keyword
  926.     assume fs:nothing
  927. CpuMode reset
  928.  
  929. ?ThunkSeg       equ <THUNK_TEXT>
  930. ?PanicSuffix    equ <bad suffix>
  931.  
  932. FARCODE macro   segname, NoPanic, NoProtReal, NoDPRINTF, NoAssertNoBuf
  933.     ?cstype = ?CS_16bit                 ;; default is 16-bit code
  934.     ?farcode = SN_DosCode               ;; Indicate low code segment
  935.     ?ASSUMECS macro
  936.         assume cs:DOSCODE
  937.     endm
  938.     ?ThunkSeg equ <THUNK_TEXT>
  939.     ?PanicSuffix equ <>
  940.     ifidn <segname>,<LOW>
  941.         ?PanicSuffix equ <LOW>
  942.     elseifidn <segname>,<INIT>
  943.         ?PanicSuffix equ <LOW>
  944.         ?ThunkSeg equ <THUNKINIT_TEXT>
  945.     elseifidn <segname>,<INITR3>
  946.         ?PanicSuffix equ <INITR3>
  947.         ?farcode = SN_DosInitR3Code     ;;  Indicate which far code segment
  948.         ?ASSUMECS macro
  949.             assume cs:DOSINITR3CODE
  950.         endm
  951.         ?ThunkSeg equ <no ring 3 thunks>
  952.     elseifidn <segname>,<HIGH2>
  953.         ?PanicSuffix equ <HIGH2>
  954.         ?farcode = SN_DosHigh2Code      ;; Indicate which far code segment
  955.         ?ASSUMECS macro
  956.             assume cs:DOSHIGH2CODE
  957.         endm
  958.     elseifidn <segname>,<HIGH3>
  959.         ?PanicSuffix equ <HIGH3>
  960.         ?farcode = SN_DosHigh3Code      ;; Indicate which far code segment
  961.         ?ASSUMECS macro
  962.             assume cs:DOSHIGH3CODE
  963.         endm
  964.     elseifidn <segname>,<HIGH4>
  965.         ?PanicSuffix equ <HIGH4>
  966.         ?farcode = SN_DosHigh4Code      ;; Indicate which far code segment
  967.         ?ASSUMECS macro
  968.             assume cs:DOSHIGH4CODE
  969.         endm
  970.     elseifidn <segname>,<HIGH32>
  971.         ?PanicSuffix equ <HIGH32>
  972.         ?farcode = SN_DosHigh32Code     ;; Indicate which far code segment
  973.         ?cstype = ?CS_32bit             ;; Mark as 32-bit code segment
  974.         ?ASSUMECS macro
  975.             assume cs:FLAT
  976.         endm
  977.     elseif2
  978.         %out FARCODE: bad segment name: segname
  979.         .err
  980.     endif
  981.     if1
  982.         ifndef _TKSSBase
  983.             ReferFlat _TKSSBase,dword
  984.         endif
  985.     endif
  986.     ifdef INTERRPRT
  987.         EXTRNFAR __panicsprintf,<NoPanic>
  988.     endif
  989.     ifdef MODECHECK
  990.         EXTRN16 TaskOnly,<NoProtReal>
  991.         EXTRNFAR TaskOnly,<NoProtReal>
  992.         EXTRNFAR ProtTaskOnly,<NoProtReal>
  993.         EXTRNFAR ProtOnly,<NoProtReal>
  994.         EXTRNFAR RealTaskOnly,<NoProtReal>
  995.         EXTRNFAR RealOnly,<NoProtReal>
  996.         EXTRNFAR RealProcTaskOnly,<NoProtReal>
  997.     endif
  998.     if Debug
  999.         EXTRNFAR DPRINTF,<NoDPRINTF>
  1000.         EXTRNFAR dbtest,<NoDPRINTF>
  1001.     endif
  1002.     ifdef FSSTRICT
  1003.         if ?farcode ne SN_DosHigh2Code
  1004.             EXTRNFAR AssertNoBufProc,<NoAssertNoBuf>
  1005.         endif
  1006.     endif
  1007.     ?ASSUMECS
  1008.     .386p
  1009.     assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
  1010.     CpuMode reset
  1011. endm
  1012.  
  1013.  
  1014. ;***    InternalError - panic when things go wrong
  1015. ;
  1016. ;       Calls Panic macro.
  1017. ;
  1018. ;       ENTRY   arg = error message to display before system halts
  1019. ;       EXIT    Panic macro invoked.
  1020.  
  1021. InternalError   macro   arg
  1022.     if (?farcode eq SN_DosCode)         ;; if in tiled code, assume realmode
  1023.         Panic <'&arg&'>,,,realmode
  1024.     else
  1025.         Panic <'&arg&'>
  1026.     endif
  1027. endm
  1028.  
  1029. ;***    Panic - print panic message and halt the system
  1030. ;
  1031. ;       This macro prints the specified panic message (with parameters) and
  1032. ;       halts the system.
  1033. ;
  1034. ;       ENTRY   fmt             - message format string
  1035. ;               parmlist        - parameter list
  1036. ;               n               - source-file-unique Panic number
  1037. ;               frealmode       - "realmode" flag
  1038. ;       EXIT    *DOES NOT RETURN*
  1039.  
  1040. PANICBASE       equ     60000   ; start high to avoid source line conflict
  1041. ?paniccnt = PANICBASE
  1042. ?PF_TILED       equ     01h
  1043. ?PF_FILE        equ     02h
  1044. ?panicfile = 0
  1045. ?panicmsgseg    equ     <bad seg>
  1046.  
  1047. Panic   macro   fmt,parmlist,n,frealmode
  1048. local fmtoff, cparms, rmode
  1049.     if2
  1050.         ifnb <frealmode>
  1051.             ifdif <frealmode>,<realmode>
  1052.                 ProcError <Panic: bad realmode arg: frealmode>
  1053.                 .err
  1054.             endif
  1055.         endif
  1056.     endif
  1057.     .386p
  1058.     ?panicfn equ <__panic>
  1059.     rmode = 0
  1060.     ifnb <frealmode>
  1061.         if (?farcode eq SN_DosCode)     ;; If in tiled code segment
  1062.             ?panicfn equ <__panicRM>
  1063.             rmode = 1
  1064.         endif
  1065.     endif
  1066.     ?om1 = 0
  1067.     ifdef INTERRPRT
  1068.         ifndef NOINTERRPRT
  1069.             ifnb <fmt>
  1070.                 ?om1 = 1                ;; display filename and message text
  1071.             endif
  1072.         endif
  1073.     endif
  1074.     if (?om1 ne 0)
  1075.         ?panicfn equ <__panicfnmsg>
  1076.         ?panicmsgseg equ <PANICMSG>
  1077.         ifnb <frealmode>                        ;; don't use rmode flag!!
  1078.  
  1079.             ;; If this invocation requires __FILE__ in the tiled data segment,
  1080.             ;; then make sure the first Panic invocation put it there.
  1081.  
  1082.             if (rmode ne 0)
  1083.                 if ((?panicfile and (?PF_FILE or ?PF_TILED)) eq ?PF_FILE)
  1084.                     if2
  1085.                         ProcError <first Panic must specify realmode>
  1086.                         .err
  1087.                     endif
  1088.                     exitm
  1089.                 endif
  1090.                 ?panicfn equ <__panicfnmsgRM>
  1091.             endif
  1092.  
  1093.             ;; Put the strings in the low (tiled) data segment if realmode was
  1094.             ;; specified in the tiled code segment (DOSCODE) OR if this is the
  1095.             ;; very first Panic invocation and the realmode flag was specified.
  1096.             ;; This allows a real mode Panic invocation to access the __FILE__
  1097.             ;; and fmtoff strings.  rmode is non-zero when InternalError was
  1098.             ;; invoked in DOSCODE.  ?panicfile is zero when this is the first
  1099.             ;; Panic invocation.
  1100.  
  1101.             if ((rmode ne 0) or (?panicfile eq 0))
  1102.                 ?panicmsgseg equ <INTERRMSG>
  1103.                 if (?panicfile eq 0)
  1104.                     ?panicfile = ?panicfile or ?PF_TILED
  1105.                 endif
  1106.             endif
  1107.         endif
  1108. %       ?Eval ?panicmsgseg <segment>            ;; put string in proper segment
  1109.             if ((?panicfile and ?PF_FILE) eq 0)
  1110.                 ifdef SCCSID
  1111.                     __FILE__  db  SCCSID, 0
  1112.                 else
  1113.                     if2
  1114. %                       %out @FileName.asm: Panic: SCCSID undefined
  1115.                         .err
  1116.                     endif
  1117. %                   __FILE__  db  '&@FileName&.asm', 0
  1118.                 endif
  1119.                 ?panicfile = ?panicfile or ?PF_FILE
  1120.             endif
  1121.             fmtoff  db  fmt, 0          ;; Format string
  1122. %       ?Eval ?panicmsgseg <ends>
  1123.  
  1124.         cparms = 0
  1125.         irp x,<parmlist>
  1126.             cparms = cparms + 1         ;; Count arguments
  1127.             PUSHD  <x>                  ;; Push arguments
  1128.         endm
  1129.         if (rmode ne 0)
  1130.             push  offset DOSGROUP:fmtoff ;; Push format string address
  1131.         else
  1132.             PUSHD <offset FLAT:fmtoff>  ;; Push FLAT format string address
  1133.         endif
  1134.         if (cparms ne 0)                ;; sprintf into a buffer
  1135.             if2
  1136.                 if (rmode ne 0)
  1137.                     ProcError <Panic: no parms in realmode>
  1138.                     .err
  1139.                 endif
  1140.                 ifdef SN_DosInitR3Code
  1141.                     if ?farcode eq SN_DosInitR3Code
  1142.                         ProcError <Panic: no parms in ring 3>
  1143.                         .err
  1144.                     endif
  1145.                 endif
  1146.             endif
  1147.             if ?cstype eq ?CS_32bit
  1148.                 ?GenCall __panicsprintf, SN_DosHigh32Code
  1149.             else
  1150.                 CALLFAR __panicsprintf
  1151.             endif
  1152.             lea  esp,[esp + (cparms * 4)]  ;; clean up the stack
  1153.             ?panicfn equ <__panicfn>
  1154.         endif
  1155.         if (rmode ne 0)
  1156.             push  offset DOSGROUP:__FILE__ ;; Push filename address
  1157.         else
  1158.             PUSHD <offset FLAT:__FILE__>   ;; Push FLAT filename address
  1159.         endif
  1160.     endif
  1161.     CpuMode reset                       ;; reset cpu mode
  1162.     if (rmode eq 0)
  1163.         ?panicfn catstr ?panicfn,?PanicSuffix;; build panic function name
  1164.     endif
  1165.     ?GenCall %?panicfn, %?farcode       ;; call panic thunk near
  1166.     if (?ModNumber eq 0ffffh)
  1167.         ?ModNumber = 0
  1168.         if2
  1169. %           %out @FileName.asm: Panic: FNO_NUM undefined - use ModName macro
  1170.             .err
  1171.         endif
  1172.     endif
  1173.     dw  ?ModNumber                      ;; store file number
  1174.     ifnb <n>
  1175.         dw  n                           ;; store specified "line number"
  1176.     else
  1177.         dw  ?paniccnt                   ;; store computed "line number"
  1178.         ?paniccnt = ?paniccnt + 1
  1179.     endif
  1180. endm
  1181.  
  1182. ;***    ModName - declare module name for debugging purpose
  1183. ;
  1184. ;       The module number is used for generating Panic file numbers.
  1185. ;
  1186. ;       ENTRY:  modname   = module name (ignored; see masm's @FileName feature)
  1187. ;               modnumber = module number (used for Panic invocations)
  1188. ;
  1189. ;       EXIT:
  1190. ;       (global variables)
  1191. ;               ?ModNumber = file number
  1192.  
  1193. ?ModNumber = 0ffffh
  1194.  
  1195. ModName macro   modname, modnumber
  1196.     ifnb <modnumber>
  1197.         ?ModNumber = modnumber
  1198.     endif
  1199. endm
  1200.  
  1201. ;***    BeginNoBlock/EndNoBlock - begin/end kernel critical section.
  1202. ;
  1203. ;       Debugging aid only.  If ProcBlocks or task switches are attempted
  1204. ;       between a BeginNoBlock/EndNoBlock pair, an internal error will result.
  1205.  
  1206. BeginNoBlock macro segreg
  1207.     ?NoBlock segreg,<inc>,<BeginNoBlock>
  1208. endm
  1209.  
  1210. EndNoBlock macro segreg
  1211.     ?NoBlock segreg,<dec>,<EndNoBlock>
  1212. endm
  1213.  
  1214. ?NoBlock macro segreg,incdec,beginend
  1215.     ifdef MISCSTRICT
  1216.         ifndef _cTKNoBlock
  1217.             ReferGlobal _cTKNoBlock, byte
  1218.         endif
  1219.         pushf
  1220.         ifnb <segreg>
  1221.  
  1222.             ;; inc FLAT:[_cTKNoBlock] generates a FLAT-relative 16 bit
  1223.             ;; offset fixup, which the linker rejects.  inc DS:[_cTKNoBlock]
  1224.             ;; with DS assumed FLAT by the caller generates a FLAT-relative
  1225.             ;; 32 bit fixup, which works ok.
  1226.  
  1227.             if2
  1228.                 ifidn <segreg>,<FLAT>
  1229.                     ProcError <beginend: masm will not allow segreg>
  1230.                     .err
  1231.                 endif
  1232.             endif
  1233.             incdec segreg:[_cTKNoBlock]         ;; inc/dec counter
  1234.         elseif (?cstype eq ?CS_32bit)
  1235.             incdec [_cTKNoBlock]                ;; inc/dec counter
  1236.         else
  1237.  
  1238.         ;; The following doesn't work if the chosen segment register is
  1239.         ;; already assumed FLAT.  In such a case, masm generates a FLAT
  1240.         ;; relative reference with a non-FLAT segment register.  We use
  1241.         ;; FS here and disallow the construct in 32 bit code in a feeble
  1242.         ;; attempt to avoid using a segment register that is assumed FLAT.
  1243.  
  1244.             .386p
  1245.             push  fs
  1246.             DosContext fs,,noassume
  1247.             incdec fs:[_cTKNoBlock]             ;; inc/dec counter
  1248.             pop   fs
  1249.             CpuMode reset
  1250.         endif
  1251.         popf
  1252.     endif
  1253. endm
  1254.  
  1255. ;***    TaskTime - enforce non-InterruptLevel execution context
  1256. ;
  1257. ;       Debugging aid only.  If running at InterruptLevel,
  1258. ;       an internal error will be generated.
  1259.  
  1260. TaskTime macro
  1261.     ifdef MODECHECK
  1262.         ?GenCall TaskOnly, SN_DosCode
  1263.     endif
  1264. endm
  1265.  
  1266. ;***    AssertCLD - Check the state of the direction flag
  1267. ;
  1268. ;       Entry: none
  1269. ;       Exit:  none
  1270. ;       Uses:  <reg>, Flags
  1271. ;
  1272. ;       Causes an internal error if the direction flag is set
  1273. ;
  1274. AssertCLD macro proc, reg
  1275. local   acld
  1276. ifdef MISCSTRICT
  1277.     ifnb <reg>
  1278.         pushf
  1279.         pop     reg
  1280.         test    reg,F_DIRECTION         ;; make sure mi.inc is included
  1281.     else
  1282.         push    ax
  1283.         pushf
  1284.         pop     ax
  1285.         test    ax,F_DIRECTION          ;; make sure mi.inc is included
  1286.         pop     ax
  1287.     endif
  1288.         jz      acld                    ;; jmp if direction flag is clear
  1289.         InternalError <&proc&: direction flag set>
  1290. acld:
  1291. endif
  1292. endm
  1293.  
  1294. ;***    AssertNoBuf - Assert that current thread isn't holding a buffer
  1295. ;
  1296. ;       AssertNoBuf is used to detect certain states that often lead to
  1297. ;       deadlock.  In particular, we'll often deadlock if we call the
  1298. ;       swapper while holding a buffer.  We can call the swapper either
  1299. ;       via a call to the memory manager, or via taking a not-present
  1300. ;       fault touching a swappable segment.  AssertNoBuf should be placed
  1301. ;       anywhere we might do these things to help catch accidentally doing
  1302. ;       them with a buffer locked.
  1303. ;
  1304. ;       AssertNoBuf is turned on by the FSSTRICT flag.
  1305. ;
  1306. ;       AssertNoBuf is by no means fool-proof, but should detect the
  1307. ;       majority of cases where we have a buffer locked.
  1308. ;
  1309. ;       ENTRY   (SS) = TASKAREA
  1310. ;       EXIT    None if OK, InternalError if error found
  1311. ;       USES    None, including flags
  1312. ;
  1313.  
  1314. AssertNoBuf macro
  1315. ifdef FSSTRICT
  1316.     ?GenCall AssertNoBufProc, SN_DosHigh2Code
  1317. endif
  1318. endm
  1319.  
  1320. ;***    DefTaskData - define resizable task control data structures
  1321. ;
  1322. ;       This macro is used to declare a task control data
  1323. ;       structure that can be resized after the maximum
  1324. ;       number of threads allowed in the system has been
  1325. ;       determined
  1326. ;
  1327. ;       INPUT   name            Name of pointer to structure
  1328. ;               width           Width of an element in structure
  1329. ;               length          Number of elements in structure
  1330. ;               value           Initial value for each element
  1331. ;               flatname        Name of flat pointer to structure
  1332.  
  1333. DefTaskData     macro   name,width,length,value,flatname
  1334.     local l
  1335.  
  1336.     CONSTANTS segment
  1337.             public name
  1338.         name  dw  offset DOSGROUP:l
  1339.     CONSTANTS ends
  1340.  
  1341.     .386p
  1342.     _DATA segment
  1343.     ifb <flatname>
  1344.             public fl_&name
  1345.         fl_&name  dd offset FLAT:l
  1346.     else
  1347.             public flatname
  1348.         flatname  dd offset FLAT:l
  1349.     endif
  1350.     _DATA ends
  1351.  
  1352.     LASTDATA segment
  1353.         dw  offset DOSGROUP:name        ;; point to pointer to this array
  1354.         ifb <flatname>
  1355.             dd  offset FLAT:fl_&name    ;; point to flat pointer to this array
  1356.         else
  1357.             dd  offset FLAT:flatname    ;; point to flat pointer to this array
  1358.         endif
  1359.         ifidni <width>,<word>
  1360.                 db  2                   ;; give the width of the item
  1361.             l   dw  length dup (value)  ;; reserve space for the item
  1362.         elseifidni <width>,<byte>
  1363.                 db  1
  1364.             l   db  length dup (value)
  1365.         elseifidni <width>,<dword>
  1366.                 db  4
  1367.             l   dd  length dup (value)
  1368.         else
  1369.                 db  width
  1370.             l   db  length dup (width dup (value))
  1371.         endif
  1372.     LASTDATA ends
  1373.     CpuMode reset
  1374. endm
  1375.  
  1376. ;***    CallGate - call API from ring3 code
  1377. ;
  1378. ;       This is for system init process or for kernel exitlist or
  1379. ;       signal dispatch code to get into kernel mode. Kernel entry
  1380. ;       looks just like an API call.
  1381. ;
  1382. ;       ENTRY:  gate = name of api routine
  1383. ;       (global variables)
  1384. ;               GDT_&gate = GDT entry defined in api.asm, api2.asm
  1385. ;
  1386. ;       EXIT:   a call instruction generated to call the call gate.
  1387.  
  1388. CallGate macro  gate
  1389. ifndef GDT_&gate
  1390.         extrn   GDT_&gate:BYTE
  1391. endif
  1392.         db      MI_LONG_CALL            ; far ret
  1393.         dw      0,GSEL GDT_&gate        ; selector of call gate
  1394. endm
  1395.  
  1396. ;***    StampRPL - Stamps the RPL of the selector parameter with the RPL
  1397. ;                  of the SS of the caller.
  1398. ;
  1399. ;       Entry:  <sel> contains selector to be stamped (not base register)
  1400. ;               <reg> contains a free index register (if it exists). It is
  1401. ;               used to access the user Stack Segment, else the bp is used.
  1402. ;               <curtcbreg> is a register that already contains [CurrTCB].
  1403. ;
  1404. ;       Exit:   Stamped selector in <sel> register
  1405. ;
  1406. ;       Uses:  <sel,reg>
  1407. ;
  1408.  
  1409. StampRPL macro sel, reg, currtcbreg
  1410.         .errnb  <currtcbreg>
  1411.         ifb <reg>
  1412.                 push    bp
  1413.                 mov     bp,ss:[TKOPTDA].CurrTSD
  1414.                 mov     bp,ss:[bp].TSDUserSS
  1415.                 arpl    sel,bp
  1416.                 pop     bp
  1417.         else
  1418.                 mov     reg,ss:[TKOPTDA].CurrTSD
  1419.                 mov     reg,ss:[reg].TSDUserSS
  1420.                 arpl    sel,reg
  1421.         endif
  1422. endm
  1423.  
  1424. ;***    JPathChar, JNPathChar
  1425. ;***    TestPathChar
  1426. ;
  1427. ;       Conditional jumps based on whether AL is a path seperator character.
  1428. ;
  1429. ;       IMPORTANT NOTE: These macros do NOT account for / as a possible
  1430. ;               path separator character.  Only \ is tested for.
  1431. ;
  1432. ;       JPathChar, JNPathChar - jump if AL contains a path char
  1433. ;               (JPathChar) or if AL does not contain a path char
  1434. ;               (JNPathChar).
  1435. ;
  1436. ;       TestPathChar - just set Z flag based on whether AL is path char.
  1437. ;               (no jump is performed).
  1438. ;
  1439. ;       ENTRY: AL: character to test
  1440. ;
  1441. ;       EXIT :  ZR: character is a path character
  1442. ;               NZ: character is not a path character
  1443. ;
  1444. ;       USES : AL
  1445. ;
  1446.  
  1447.  
  1448. JPathChar MACRO target
  1449.         cmp     al,'\'
  1450.         je      target
  1451. ENDM
  1452.  
  1453. JNPathChar MACRO target
  1454.         cmp     al,'\'
  1455.         jne     target
  1456. ENDM
  1457.  
  1458. TestPathChar MACRO
  1459.         cmp     al,'\'
  1460. ENDM
  1461.