Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2666 lines
66 KiB

  1. comment $
  2. cmacros - assembly macros for interfacing to hlls
  3. (C)Copyright Microsoft Corp. 1984-1988
  4. $
  5. ;; Revision History
  6. ;;
  7. ;; 1.00 05/03/84 Initial Release
  8. ;;
  9. ;; 1.01 05/06/84 Greg Whitten
  10. ;; Added defgrp and changed cMerge to Microsoft C
  11. ;; Added copyright message and changed to 1.01
  12. ;; Changes should have no affect on working programs
  13. ;;
  14. ;; 1.02 07/10/84 Steve Wood
  15. ;; Added labelx macros
  16. ;;
  17. ;; 1.03 07/14/84 Greg Whitten
  18. ;; Added defines for ?pu, ?adj, ?lblpu
  19. ;; (removes undefined errors)
  20. ;; Changes should have no affect on working programs
  21. ;;
  22. ;; 1.04 07/18/84 Greg Whitten
  23. ;; Added local control from PL/M or C conventions
  24. ;; except for cCall macro
  25. ;;
  26. ;; 1.05 08/06/84 Steve Wood
  27. ;; Made ?PLM and ?WIN be the defaults
  28. ;;
  29. ;; 1.06 01/02/85 Steve Wood
  30. ;; Changed createSeg and defgrp to automatically
  31. ;; define the ln_assumes macro and the lnoffset
  32. ;; and lnbase equates for each logical segment
  33. ;; name.
  34. ;;
  35. ;; 1.07 02/19/85 Walt Moore
  36. ;; Added farptr macro for defining a far pointer
  37. ;; to be used in a cCall. Folded regptr into
  38. ;; farptr. Space compaction in macros. Changed
  39. ;; ?pp to be smaller. Moved ?ia out of ?al1 into
  40. ;; ?aloc. Merged cProc and ?pd into one macro.
  41. ;; Changed some %outs to use the error macro so
  42. ;; an error would be generated. Added makeframe
  43. ;; and parmR to cProc. Changed error to also put
  44. ;; the error message in the listing.
  45. ;; Deleted the smashes macro.
  46. ;;
  47. ;; 1.08 03/18/85 Steve Wood
  48. ;; Added NODATA support.
  49. ;;
  50. ;; 1.09 03/27/85 Steve Wood
  51. ;; Added ?definitions
  52. ;;
  53. ;; 2.00 04/01/85 Steve Wood
  54. ;; April fools
  55. ;;
  56. ;; 2.01 06/17/85 Steve Wood
  57. ;; Changed NODATA to always generate POP DS
  58. ;; for return address patching
  59. ;;
  60. ;; 2.02 02/11/86 Steve Wood
  61. ;; Added ATOMIC keyword to cProc macro
  62. ;; Changed far epilog to use LEA SP,BP-2
  63. ;; Changed error macro to ??error to avoid
  64. ;; conflict
  65. ;;
  66. ;; 2.03 03/06/86 Steve Wood
  67. ;; Fixed bug with ATOMIC and locals in far proc
  68. ;; Added DOS5 switch to disable INC/DEC BP
  69. ;; instructions in special far prologs/epilogs
  70. ;;
  71. ;; 2.04 08/07/86 Scott Randell
  72. ;; Fixed bug with ATOMIC and ?TF
  73. ;; (was doing unnecessary MOV SP,BP)
  74. ;; Added pcode profile ?PROFILE
  75. ;;
  76. ;; 2.05 08/12/86 Walt Moore
  77. ;; Changed _TEXT alignment to word.
  78. ;; Added/corrected some comments.
  79. ;; Removed redundant init of ?pc in cProc
  80. ;; Made ATOMIC require NODATA
  81. ;; Moved definition of non-underscored 'C' label
  82. ;; from the cProc to the cBegin macro
  83. ;; Minor clean-up of code
  84. ;;
  85. ;; 2.06 09/11/86 Walt Moore
  86. ;; Added private stack checking
  87. ;; Put local control for PL/M or C into cCall
  88. ;;
  89. ;;
  90. ;; 2.07 09/19/86 Steve Wood
  91. ;; Added ?SMALL, ?MEDIUM, etc. symbols
  92. ;; Added forceframe keyword to cProc macro.
  93. ;; Interpret ?TF for all epilogs.
  94. ;;
  95. ;; 3.xx.a 02/26/87 Massive rework. Documentation coming.
  96. ;;
  97. ;;
  98. ;; Assembly macros for interfacing to C
  99. ;;
  100. ;; User setable conditional assembly flags used within the cmacros
  101. ;;
  102. ;; Memory model flags. Set only one of the following. memS is the
  103. ;; default. The symbols with ? are for defining from the command line
  104. ;; and the memx symbols are numeric symbols that can be set in your source
  105. ;; file prior to including this file.
  106. ;;
  107. ;; ?SMALL memS - small model
  108. ;; ?MEDIUM memM - medium model
  109. ;; ?LARGE memL - large model
  110. ;; ?COMPACT memC - compact model
  111. ;; ?HUGE memH - huge model
  112. ;;
  113. ;; ?DF Define flag. If this flag is 0, then defines default segment
  114. ;; and group definitions based on the compiler flag. If this
  115. ;; flag is 1, then does not define any segments or groups.
  116. ;;
  117. ;; ?TF Tight flag. If this flag is 0, then use longer epilog
  118. ;; sequence that safely cleans up a stack frame. If this flag is
  119. ;; 1, then use more efficient epilog that assumes the stack is
  120. ;; valid (SP)
  121. ;;
  122. ;; ?WIN Windows flag. Enables generation of special prolog/epilog
  123. ;; for far procedures. Default value is 1 (Windows).
  124. ;;
  125. ;; DOS5 If defined, then special far prolog/epilog seqeuences will not
  126. ;; include the INC/DEC BP instructions.
  127. ;;
  128. ;; PMODE Protect mode flag. Enables use of ENTER/LEAVE, disables
  129. ;; INC/DEC BP instructions, sets .286p.
  130. ;;
  131. ;; ?386regs Enables use of eax,ebx,ecx,esi,edi,fs,gs as registers
  132. ;; in cProc et al. Use of al,ah,bl,bh,cl,ch,dl,dh,ss,bp,sp,ss,cs
  133. ;; no longer allowed.
  134. ;;
  135. ;; ?PLM Calling convention flag. If this flag is 0, then the
  136. ;; calling convention used is that of C. If this flag
  137. ;; is 1, then the PL/M calling convention is used.
  138. ;; The default value is 1. The PL/M calling convention
  139. ;; is used by pascal, fortran, basic, and cobol.
  140. ;;
  141. ;; In the C calling convention, arguments are passed
  142. ;; in reverse order; arg0 is the last pushed, argn is the
  143. ;; first pushed. also, it is the callers responsibility
  144. ;; to remove the arguments from the stack upon a return
  145. ;; from a call.
  146. ;;
  147. ;; In the PL/M calling comvention, arguments are passed
  148. ;; as encountered; arg0 is the first pushed, argn is the
  149. ;; last pushed. also, it is the called procedure's
  150. ;; responsibility to remove parameters from the stack
  151. ;; before returning (using the RET n instruction)
  152. ;;
  153. ;; ?NODATA If defined, then no data segment or DGROUP is defined and
  154. ;; the special prolog/epilog sequences will not contain the
  155. ;; code needed to setup DS.
  156. ;;
  157. ;; ?CHKSTK If defined, then prolog sequences for cProcs with local
  158. ;; parameters will call the CHKSTK procedure to allocate
  159. ;; the stack space.
  160. ;;
  161. ;; ?CHKSTKPROC If defined, then this macro will be invoked to
  162. ;; perform the stack checking, otherwise the
  163. ;; standard stack checking procedure will be
  164. ;; performed. ?CHKSTKPROC must be declared
  165. ;; before the cmacros are included in the source
  166. ;; else the standard chkstk routine will be declared
  167. ;; as an external symbol.
  168. ;;
  169. ;; On entry to the user's stack checking procedure,
  170. ;; the frame has been setup except for allocating
  171. ;; local variable space and saving autosave registers.
  172. ;;
  173. ;; The user supplied macro is passed as an argument
  174. ;; the number of byte of stack space requested.
  175. ;;
  176. ;; ?PROFILE If defined then all far cBegin entries will have StartNMeas,
  177. ;; and all cEnd will have StopNMeas calls, StartNMeas and
  178. ;; StopNMeas will be defined as externfp
  179. ;;
  180. ;; ?NOPARMR If defined, then the "parmR" macro will not be defined.
  181. ;;
  182. ;; ?NOGLOBAL If defined, then the "globalx" macros will not be defined.
  183. ;;
  184. ;; ?NOSTATIC If defined, then the "staticx" macros will not be defined.
  185. ;;
  186. ;; ?NOEXTERN If defined, then the "externx" macros will not be defined.
  187. ;;
  188. ;; ?NOLABEL If defined, then the "labelx" macros will not be defined.
  189. ;;
  190. ;; ?NODEF If defined, then the "defx" macros will not be defined.
  191. ;;
  192. ;; ?NOPTR If defined, then "farptr & regptr" will not be defined.
  193. ;;
  194. ;; ?QUIET If defined, then only error messages will be issued to
  195. ;; the console. If undefined, then certain cmacro text will
  196. ;; be generated to the console.
  197. .xcref ;;Get rid of a lot of symbols
  198. ; ??_out - output given message to the console unless ?QUIET has
  199. ; been specified.
  200. ;
  201. ; usage:
  202. ; ??_out <t>
  203. ;
  204. ; where:
  205. ; <t> is the message to output
  206. .xcref ??_out
  207. ??_out macro t
  208. ifndef ?QUIET
  209. %out t
  210. endif
  211. endm
  212. ; outif - output msg if name is non-zero. if name is undefined,
  213. ; set name = 0, else set name to the default value.
  214. ;
  215. ; usage:
  216. ; outif name,defval,onmsg,offmsg
  217. ; where:
  218. ; name name of symbol
  219. ; defval default value to give symbol if not defined
  220. ; if blank, then 0 will be used
  221. ; onmsg text to display if symbol is non-zero
  222. ; offmsg test to be displayed if symbol is zero
  223. outif macro name,defval,onmsg,offmsg
  224. ifndef name
  225. ifb <defval>
  226. name=0
  227. else
  228. name=defval
  229. endif
  230. endif
  231. if name
  232. name=1
  233. ifnb <onmsg>
  234. ??_out <! onmsg>
  235. endif
  236. else
  237. ifnb <offmsg>
  238. ??_out <! offmsg>
  239. endif
  240. endif
  241. endm
  242. ; ??error - output msg and generate an assembly time error
  243. ;
  244. ; usage:
  245. ; ??error <t>
  246. ; where:
  247. ; t is the text to be output
  248. .xcref ??error
  249. ??error macro msg
  250. e r r o r ----- msg ;;to console
  251. .err ;;for good measure, force this also
  252. endm
  253. .xcref ASMpass
  254. .xcref memS,memM,memL,memC,memH,memMOD,sizec,sized
  255. if1 ;;Only on pass 1
  256. ASMpass=1
  257. ifdef ?SMALL ;;inform user what is going on
  258. memS=1
  259. endif
  260. ifdef ?MEDIUM
  261. memM=1
  262. endif
  263. ifdef ?COMPACT
  264. memC=1
  265. endif
  266. ifdef ?LARGE
  267. memL=1
  268. endif
  269. ifdef ?HUGE
  270. memH=1
  271. endif
  272. ??_out <cMacros Version 5.20 - Copyright (c) Microsoft Corp. 1984-1988>
  273. outif memS,0,<Small model>
  274. outif memM,0,<Medium model>
  275. outif memL,0,<Large model>
  276. outif memC,0,<Compact model>
  277. outif memH,0,<Huge model>
  278. memMOD= memS + memM + memL + memC + memH
  279. if memMOD ne 1
  280. if memMOD eq 0
  281. memS = 1 ; assume small model
  282. else
  283. ??error <more than 1 memory model selected>
  284. endif
  285. endif
  286. sizec= memM + memL + memH ; large code
  287. sized= memL + memC + (memH*2) ; large data (2 if huge)
  288. outif ?DF,0,<No segments or groups will be defined>
  289. outif ?TF,0,<Epilog sequences assume valid SP>
  290. outif ?WIN,1,<Windows support>
  291. ifdef PMODE
  292. ?pmd=1
  293. ??_out <! 286 protect mode>
  294. else
  295. ?pmd=0
  296. endif
  297. ifdef ?386regs
  298. if ?386regs
  299. ??_out <! 386 registers enabled>
  300. endif
  301. else
  302. ?386regs=0
  303. endif
  304. if ?WIN eq 1
  305. outif ?PLM,1,<>
  306. else
  307. outif ?PLM,1,<Pascal calling convention>
  308. endif
  309. ifndef ?NODATA
  310. ?nodata1=0
  311. else
  312. ?nodata1=1
  313. ??_out <! NODATA module>
  314. endif
  315. ifndef ?CHKSTK
  316. ?chkstk1=0
  317. else
  318. ?chkstk1=1
  319. ifdef ?CHKSTKPROC
  320. ??_out <! Private stack checking enabled>
  321. else
  322. ??_out <! Stack checking enabled>
  323. endif
  324. endif
  325. ifndef DOS5
  326. ?DOS5=0
  327. else
  328. ?DOS5=1
  329. ??_out <! DOS5 module>
  330. endif
  331. ifdef ?PROFILE
  332. ??_out <! Native profiling enabled>
  333. endif
  334. else
  335. ASMpass=2
  336. endif
  337. ifdef ?pmd
  338. .286p
  339. endif
  340. ;; Initialize all symbols used in the macros. Theses symbols will not be
  341. ;; included in any cross reference listing.
  342. if ?386regs
  343. .xcref ?n,?ax,?eax,?bx,?ebx
  344. .xcref ?cx,?ecx,?dx,?edx
  345. .xcref ?si,?esi,?di,?edi,?es,?ds,?fs
  346. .xcref ?gs
  347. else
  348. .xcref ?n,?ax,?ah,?al,?bx,?bh
  349. .xcref ?bl,?cx,?ch,?cl,?dx,?dh
  350. .xcref ?dl,?si,?di,?es,?ds,?bp
  351. .xcref ?sp,?ss,?cs
  352. endif
  353. .xcref ?rsl,?cpd,?argl,?argc,?ba
  354. .xcref ?acb,???,?po
  355. .xcref ?pas,?pc
  356. .xcref uconcat,mpush,mpop
  357. .xcref ?ri,?pp,?pp1,?al1
  358. .xcref ?ad,?ap,?atal,?dd,?dd1,?dd2
  359. .xcref ?pg,?pg1,?aloc,?cs1,?cs2
  360. .xcref ?DF,?TF,?ff,?PLM,?WIN,?ia,?pu,?adj
  361. .xcref ?uf,?rp,?nx,?nd,?nodata1,?chkstk1,?DOS5,?pmd,?lds,?exp
  362. .xcref ?wfp,arg,cCall,cProc,assumes,?cs3,?cs2,?cs1
  363. .xcref defgrp,addseg,createSeg
  364. .xcref save,outif,errnz,errn$,errnz1
  365. .xcref ?PLMPrevParm,?gcc
  366. .xcref ?cCall1,?pcc
  367. ;; conditionals set by the macros
  368. ;;
  369. ;; ?pc Procedure class. If this is set to 1, then the procedure
  370. ;; is a far procedure, else it is a near procedure.
  371. ;;
  372. ;; ?ia Interface adjustment count for far procedures. The
  373. ;; interface adjustment defines the number of bytes of
  374. ;; storage allocated between BP and the first frame variable
  375. ;; allocated on the stack.
  376. ;;
  377. ;; Normally zero, it will be adjusted for both far windows
  378. ;; procedures and by register parameters.
  379. ;;
  380. ;; ?cpd Current procedure defined. This is set to a non-zero
  381. ;; value if a procedure is being defined (i.e a cProc has
  382. ;; been encountered, and cBegin has not).
  383. ;;
  384. ;; ?ba Begin active. This is set to a non-zero value if a
  385. ;; cBegin is active (i.e. a cBegin has been encountered,
  386. ;; and cEnd has not).
  387. ;;
  388. ;; ?wfp Windows far procedure. Set if a windows far procedure
  389. ;;
  390. ;; ?lds LOADDS keyword - Preserve DS and set DS to _DATA
  391. ;;
  392. ;; ?exp EXPORTED keyword - mov ax,ds/nop as first inst, preserve DS
  393. ;;
  394. ;; Other variables that are defined once so that the .xcref command
  395. ;; doesn't get too upset if they show up missing!
  396. ?rsl = 0 ;;0 = no register to save
  397. ?cpd = 0 ;;<> 0 if in a procedure definition
  398. ?argl = 0 ;;length of arguments pushed on stack
  399. ?argc = 0 ;;# of arguments so far
  400. ?ba = 0 ;;<>0 if in a procedure (xbegin)
  401. ?acb = 0 ;;number of arguments to a call
  402. ??? = 0 ;;byte count of local storage
  403. ?po = 0 ;;byte count of parameters
  404. ?pas = 0 ;;autosave value for procedure
  405. ?pc = 0 ;;class of a procedure (near/far)
  406. ?ia = 0 ;;no adjustment
  407. ?pu = 0 ;;public flag for some macros
  408. ?adj = 0 ;;initial define for .xcref
  409. ?rp = 0 ;;count of register parameters
  410. ?uf = 0 ;;user's frame code specified
  411. ?nd = 0 ;;NODATA keyword specified
  412. ?nx = 0 ;;ATOMIC keyword specified
  413. ?wfp = 0 ;;window far procedure
  414. ?lds = 0 ;;LOADDS keyword
  415. ?exp = 0 ;;EXPORTED keyword
  416. ?ff = 0 ;;forceframe keyword specified
  417. ?dd2 = 0 ;;used for globalx and staticx
  418. ?cCall1 = 0 ;;used for cCalls
  419. ?pcc = 0 ;;procedure calling convention
  420. ?PLMPrevParm = 0 ;;Used in parameter processing
  421. .xcref ?casen
  422. if1 ;;only define ?casen on pass 1
  423. ?casen = 0 ;;case sensitive assembly if <> 0
  424. endif
  425. if ?386regs
  426. ?n = 0000000000000000b
  427. ?ax = 0000000000000001b
  428. ?eax = 0000000000000010b
  429. ?bx = 0000000000000100b
  430. ?ebx = 0000000000001000b
  431. ?cx = 0000000000010000b
  432. ?ecx = 0000000000100000b
  433. ?dx = 0000000001000000b
  434. ?edx = 0000000010000000b
  435. ?si = 0000000100000000b
  436. ?esi = 0000001000000000b
  437. ?di = 0000010000000000b
  438. ?edi = 0000100000000000b
  439. ?ds = 0001000000000000b
  440. ?es = 0010000000000000b
  441. ?fs = 0100000000000000b
  442. ?gs = 1000000000000000b
  443. else
  444. ?n = 0000000000000000b ;;register none
  445. ?ax = 0000000000000011b ;;register ax
  446. ?ah = 0000000000000001b ;;register ah
  447. ?al = 0000000000000010b ;;register al
  448. ?bx = 0000000000001100b ;;register bx
  449. ?bh = 0000000000000100b ;;register bh
  450. ?bl = 0000000000001000b ;;register bl
  451. ?cx = 0000000000110000b ;;register cx
  452. ?ch = 0000000000010000b ;;register ch
  453. ?cl = 0000000000100000b ;;register cl
  454. ?dx = 0000000011000000b ;;register dx
  455. ?dh = 0000000001000000b ;;register dh
  456. ?dl = 0000000010000000b ;;register dl
  457. ?si = 0000000100000000b ;;register si
  458. ?di = 0000001000000000b ;;register di
  459. ?es = 0000010000000000b ;;register es
  460. ?ds = 0000100000000000b ;;register ds
  461. ?bp = 0001000000000000b ;;register bp
  462. ?sp = 0010000000000000b ;;register sp
  463. ?ss = 0100000000000000b ;;register ss
  464. ?cs = 1000000000000000b ;;register cs
  465. endif
  466. .cref
  467. ;; uconcat - unconditionally generate a statement from a field
  468. ;; of given parameters
  469. ;;
  470. ;; usage:
  471. ;; uconcat a,b,c,d,e,f,g
  472. ;;
  473. ;; where:
  474. ;; a,b are concatenated for field 1
  475. ;; c,d are concatenated for field 2
  476. ;; e,f,g are concatenated for field 3
  477. uconcat macro a,b,c,d,e,f,g
  478. a&b c&d e&f&g
  479. endm
  480. ;; mpush pushes multiple registers onto the stack according to
  481. ;; a register specification.
  482. ;;
  483. ;; format:
  484. ;; mpush r
  485. ;;
  486. ;; where:
  487. ;; r is a numeric expression returned from ?ri
  488. ;; or any other valid register expression
  489. if ?386regs
  490. mpush macro r
  491. irp x,<ax,eax,bx,ebx,cx,ecx,dx,edx,si,esi,di,edi,ds,es,fs,gs>
  492. if (r and ?&&x)
  493. push x ;@
  494. endif
  495. endm
  496. endm
  497. else
  498. mpush macro r
  499. irp x,<ax,bx,cx,dx,si,di,es,ds,bp,sp,ss,cs>
  500. if (r and ?&&x)
  501. push x ;@
  502. endif
  503. endm
  504. endm
  505. endif
  506. ;; mpop pops multiple registers from the stack according to
  507. ;; a register specification.
  508. ;;
  509. ;; format:
  510. ;; mpop r
  511. ;;
  512. ;; where:
  513. ;; r is a numeric expression returned from ?ri
  514. ;; or any other valid register expression
  515. if ?386regs
  516. mpop macro r
  517. irp x,<gs,fs,es,ds,edi,di,esi,si,edx,dx,ecx,cx,ebx,bx,eax,ax>
  518. if (r and ?&&x)
  519. pop x ;@
  520. endif
  521. endm
  522. endm
  523. else
  524. mpop macro r
  525. irp x,<cs,ss,sp,bp,ds,es,di,si,dx,cx,bx,ax>
  526. if (r and ?&&x)
  527. pop x ;@
  528. endif
  529. endm
  530. endm
  531. endif
  532. ;; save - flag that the indicated registers are to be saved/restored
  533. ;;
  534. ;; A flag is created which indicates which registers are to be saved
  535. ;; when the cCall macro is invoked, and then restored after the call.
  536. ;;
  537. ;; usage:
  538. ;; save <r>
  539. ;;
  540. ;; where r is the list of registers to save, which may be:
  541. ;;
  542. ;; register saves
  543. ;; AX AX
  544. ;; AH AX
  545. ;; AL AX
  546. ;; BX BX
  547. ;; BH BX
  548. ;; BL BX
  549. ;; CX CX
  550. ;; CH CX
  551. ;; CL CX
  552. ;; DX DX
  553. ;; DH DX
  554. ;; DL DX
  555. ;; SI SI
  556. ;; DI DI
  557. ;; ES ES
  558. ;; DS DS
  559. ;; BP BP
  560. ;;
  561. ;; none nothing
  562. ;;
  563. ;; the macro generates a value for the variable ?rsl
  564. save macro r
  565. ?rsl=0 ;;initialize save list
  566. ?ri ?rsl,<r> ;;generate magic number
  567. endm
  568. ;; ?ri - or register indexes to variable
  569. ;;
  570. ;; ?ri is a macro that examines the passed argument list and computes
  571. ;; a register index variable.
  572. ;;
  573. ;; The values ORed with the variable are:
  574. ;;
  575. ;; ?n equ 0000000000000000b;
  576. ;; ?AX equ 0000000000000011b;
  577. ;; ?AH equ 0000000000000001b;
  578. ;; ?AL equ 0000000000000010b;
  579. ;; ?BX equ 0000000000001100b;
  580. ;; ?BH equ 0000000000000100b;
  581. ;; ?BL equ 0000000000001000b;
  582. ;; ?CX equ 0000000000110000b;
  583. ;; ?CH equ 0000000000010000b;
  584. ;; ?CL equ 0000000000100000b;
  585. ;; ?DX equ 0000000011000000b;
  586. ;; ?DH equ 0000000001000000b;
  587. ;; ?DL equ 0000000010000000b;
  588. ;; ?SI equ 0000000100000000b;
  589. ;; ?DI equ 0000001000000000b;
  590. ;; ?ES equ 0000010000000000b;
  591. ;; ?DS equ 0000100000000000b;
  592. ;; ?BP equ 0001000000000000b;
  593. ;; ?SP equ 0010000000000000b;
  594. ;; ?SS equ 0100000000000000b;
  595. ;; ?CS equ 1000000000000000b;
  596. ;; usage:
  597. ;; ?ri n,<r>
  598. ;; where:
  599. ;; n is the variable to contain the new index value
  600. ;; r is the register list
  601. ?ri macro n,r
  602. irp x,<r>
  603. .ERRNDEF ?&&x ;; yell if register isn't defined
  604. n=n or ?&&x
  605. endm
  606. endm
  607. ;; parmx - generate reference to parameter(s) on the stack
  608. ;;
  609. ;; An equate is generated for addressing a paramter(s)
  610. ;; on the stack for the current procedural frame.
  611. ;;
  612. ;; An error message is generated if there isn't a current frame.
  613. ;;
  614. ;; usage:
  615. ;; parmx n
  616. ;; where:
  617. ;; x is the type of the argument(s) b=byte, w=word, d=dword
  618. ;; n is the name(s) to be given the parameter(s).
  619. ;;
  620. ;; Bytes are considered to be two bytes long for alignment.
  621. ;;
  622. ;; The parmd form of the macro generates three equates:
  623. ;;
  624. ;; name - for accessing the parameter as a double word
  625. ;; off_name - for accessing the offset (lsw) of the parameter
  626. ;; seg_name - for accessing the segment (msw) of the parameter
  627. .xcref
  628. .xcref parmB,parmW,parmD,parmQ,parmT,parmCP,parmDP
  629. .cref
  630. parmB macro n
  631. ?pp <n>,<byte>,2,1
  632. endm
  633. parmW macro n
  634. ?pp <n>,<word>,2,2
  635. endm
  636. parmD macro n
  637. ife ?PLM ;;if to assemble for C
  638. irp x,<n>
  639. ?pp <&&x>,<dword>,0,4
  640. ?pp <off_&&x>,<word>,2,2
  641. ?pp <seg_&&x>,<word>,2,2
  642. endm
  643. else ;;if to assemble for PL/M
  644. irp x,<n>
  645. ?pp <seg_&&x>,<word>,2,2
  646. ?pp <off_&&x>,<word>,2,2
  647. ?pp <&&x>,<dword>,0,4
  648. endm
  649. endif
  650. endm
  651. parmQ macro n
  652. ?pp <n>,<qword>,8,8
  653. endm
  654. parmT macro n
  655. ?pp <n>,<tbyte>,10,10
  656. endm
  657. if sizec
  658. parmCP macro n
  659. parmD <n>
  660. endm
  661. else
  662. parmCP macro n
  663. parmW <n>
  664. endm
  665. endif
  666. if sized
  667. parmDP macro n
  668. parmD <n>
  669. endm
  670. else
  671. parmDP macro n
  672. parmW <n>
  673. endm
  674. endif
  675. ;; ?pp is the generalized parameter definition macro
  676. ;;
  677. ;; usage:
  678. ;; ?pp m,t,l,s
  679. ;;
  680. ;; where:
  681. ;; n is the name(s) of the parameters
  682. ;; t is the type (word, dword)
  683. ;; l is the length to update parameter byte count by
  684. ;; s is the internal typing size
  685. ?pp macro n,t,l,s ;;process parameter
  686. if ?cpd ;;must be in a procedure definition
  687. .xcref
  688. irp x,<n>
  689. .xcref ?t&&x ;;don't want this in xref
  690. ?t&&x=s ;;save size info
  691. ife ?PLM ;;if C calling convention
  692. ?pp1 x,<t>,,,%(?po+?adj)
  693. ?po=?po+l ;;update parameter offset
  694. else ;;else assemble for PL/M
  695. ?PLMPrevParm=?PLMPrevParm+1 ;;Show next parameter
  696. ?po=?po+l ;;update parameter offset
  697. ?pp1 x,<t>,%?po,%?adj,,%?PLMPrevParm,%(?PLMPrevParm-1)
  698. endif
  699. endm
  700. .cref
  701. else
  702. ??error <parm(s) "&n" declared outside proc def>
  703. endif
  704. endm
  705. ;; ?pp1 is the macro that generates the text equate for the
  706. ;; parameter. Two options exist, one for the C calling
  707. ;; convention where the last parameter was the first pushed onto
  708. ;; the stack ('C' convention), and one for the PL/M calling
  709. ;; convention where the first parameter was the first
  710. ;; pushed (also the same as ms-pascal).
  711. ;;
  712. ;; The text generated will be of one of two forms:
  713. ;;
  714. ;; name equ (type ptr [bp+(adj+offset)]) for C
  715. ;; or
  716. ;; name equ (type ptr [bp+adj+?po-offset]) for PL/M
  717. ;;
  718. ;;
  719. ;; For C, since parameters are pushed first last, the offset
  720. ;; plus the adjust will point to the correct parameter.
  721. ;;
  722. ;; For PL/M, since parameters are pushed first first, the offset
  723. ;; of a parameter is much more complicated. A known portion of
  724. ;; the offset can be computed when the text equate is generated.
  725. ;;
  726. ;; What is known is the number of garbage bytes between BP and
  727. ;; the nearest parameter (in this case the last parameter), and
  728. ;; also how many bytes of parameters have preceeded this parameter.
  729. ;;
  730. ;; What is unknown is how many total bytes of parameters there will
  731. ;; be, which affects all the generated text equates since the offset
  732. ;; from bp must be determined at some point.
  733. ;;
  734. ;; Well, the offset from BP can be computed with one variable if
  735. ;; the following is remembered:
  736. ;;
  737. ;; the offset of any parameter from the first parameter is always
  738. ;; the current parameter offset (?po).
  739. ;;
  740. ;; With this in mind, you just have to figure out where the first
  741. ;; parameter is, which is:
  742. ;;
  743. ;; bp + garbage adjustment + distance to first parameter
  744. ;; or
  745. ;; bp + ?adj + ?po
  746. ;;
  747. ;; This implies that any parameter can be defined as:
  748. ;;
  749. ;; bp + ?adj + ?po -%?po
  750. ;;
  751. ;; Make any sense?
  752. ;;
  753. ;; For PL/M, a chain of self-purging macros will be generated
  754. ;; which will pass the evaluated ?po to any previous incarnation
  755. ;; of the macro. This will allow the text equate to be generated
  756. ;; with the actual offset instead of the symbolic ?po.
  757. ;;
  758. ;;
  759. ;; usage:
  760. ;; ?pp1 n,t,o,a,b,cpc,ppc
  761. ;;
  762. ;; where:
  763. ;; n is the name to be given the equate
  764. ;; t is the type (byte, word, dword)
  765. ;; o is the offset from the first parameter
  766. ;; a is the adjustment
  767. ;; b is the adjustment plus the offset from the first parameter
  768. ;; cpc is the number of parameters so far
  769. ;; ppc is cpc - 1
  770. ?pp1 macro n,t,o,a,b,cpc,ppc
  771. ife ?PLM ;;if to generate for C
  772. n equ (t ptr [bp+b])
  773. else ;;else generate for PL/M
  774. .xcref
  775. .xcref ?PLMParm&cpc
  776. .cref
  777. ?PLMParm&cpc &macro po
  778. uconcat <n>,,<equ>,,<(t ptr [bp+>,%(a+po-o),<])>
  779. ?PLMParm&ppc po
  780. purge ?PLMParm&cpc
  781. &endm
  782. endif
  783. endm
  784. ;; parmR - register parameter
  785. ;;
  786. ;; parmR is the macro used for generating register parameters.
  787. ;; The space allocated for the register parameters will be
  788. ;; the ?ia (interface adjust) area which is between the old
  789. ;; BP and the first parameter. Normally this is empty (?ia=0),
  790. ;; or has the saved ds for a windows far procedure.
  791. ;;
  792. ;; Byte and dword register parameters will be allowed.
  793. ;;
  794. ;; usage:
  795. ;; parmR n,r,r2
  796. ;; where:
  797. ;; n is the name of the parameter
  798. ;; r is the register it is in
  799. ;; r2 is the offset register if a dword
  800. ifndef ?NOPARMR
  801. if ?pmd
  802. parmR macro n,r,r2
  803. ??error <Sorry: ParmR can't be used with PMODE=1>
  804. endm
  805. else
  806. .xcref
  807. .xcref ?pr,parmR
  808. .cref
  809. parmR macro n,r,r2
  810. ?pr n,r,r2,%?rp,%(?ia+2)
  811. endm
  812. ;; ?pr - register parameter
  813. ;;
  814. ;; ?pr is the actual macro for generating the equates for
  815. ;; register parameters.
  816. ;;
  817. ;; usage:
  818. ;; parmR n,r,r2,i,o
  819. ;; where:
  820. ;; n is the name of the parameter
  821. ;; r is the register it is in
  822. ;; r2 is the offset register if a dword
  823. ;; i is the index of the ?rp to generate
  824. ;; o is the offset from bp where the parm will be
  825. ?pr macro n,r,r2,i,o
  826. .xcref
  827. ifnb <r2> ;;if a dword parameter
  828. parmR seg_&n,r ;;define segment equate
  829. parmR off_&n,r2 ;;define offset equate
  830. n equ (dword ptr [bp-o-2]) ;;define dword equate
  831. .xcref ?t&n
  832. ?t&n=4 ;;show a dword to cmacros
  833. else
  834. .xcref ?rp&i
  835. ?rp&i=0 ;;show no register(s)
  836. ifdef ?&r ;;define register if valid
  837. ?rp&i=?&r
  838. endif
  839. if ??? or (?cpd eq 0) or (?rp&i eq 0)
  840. ??error <invalid parmR encountered: &n,&r>
  841. exitm
  842. endif
  843. n equ (word ptr [bp-o]) ;;assume a word register
  844. ?t&n=2 ;;show a word to cmacros
  845. irp x,<bh,ch,dh,bl,cl,dl,ah,al>
  846. if ?&&x eq ?&r ;;if really a byte register
  847. n equ (byte ptr [bp-o]) ;; then make it a byte
  848. ?t&n=1 ;;show a byte to cmacros
  849. exitm
  850. endif
  851. endm
  852. ?ia=?ia+2 ;;show this guy is out there
  853. ?rp=?rp+1 ;;show one more register parameter
  854. endif
  855. .cref
  856. endm
  857. endif
  858. endif
  859. ;; localx - generate reference to a local variable on the stack
  860. ;;
  861. ;; An equate is generated for addressing a local variable
  862. ;; on the stack for the current procedural frame.
  863. ;;
  864. ;; usage:
  865. ;; localx n
  866. ;; where:
  867. ;; x is the type b=byte, w=word, d=dword, v=variable size
  868. ;; n is the name(s) to be given the variable(s).
  869. ;;
  870. ;; Bytes are considered to be two bytes long for alignment reasons
  871. ;;
  872. ;; The locald form of the macro generates three equates:
  873. ;;
  874. ;; name - for accessing the variable as a double word
  875. ;; off_name - for accessing the offset (lsw) of the variable
  876. ;; seg_name - for accessing the segment (msw) of the variable
  877. .xcref
  878. .xcref localB,localW,localD,localQ,localT,localCP,localDP,localV
  879. .cref
  880. localB macro n
  881. ?aloc <n>,<byte ptr>,1,1,0 ;; no alignment
  882. endm
  883. localW macro n
  884. ?aloc <n>,<word ptr>,2,2,1 ;; word aligned
  885. endm
  886. localD macro n
  887. irp x,<n>
  888. ?aloc <seg_&&x>,<word ptr>,2,2,1 ;; word aligned
  889. ?aloc <off_&&x>,<word ptr>,2,2,1 ;; word aligned
  890. ?aloc <&&x>,<dword ptr>,0,4,1 ;; word aligned
  891. endm
  892. endm
  893. localQ macro n
  894. ?aloc <n>,<qword ptr>,8,8,1 ;; word aligned
  895. endm
  896. localT macro n
  897. ?aloc <n>,<tbyte ptr>,10,10,1 ;; word aligned
  898. endm
  899. if sizec
  900. localCP macro n
  901. localD <n>
  902. endm
  903. else
  904. localCP macro n
  905. localW <n>
  906. endm
  907. endif
  908. if sized
  909. localDP macro n
  910. localD <n>
  911. endm
  912. else
  913. localDP macro n
  914. localW <n>
  915. endm
  916. endif
  917. localV macro n,a
  918. ?aloc <n>,,%(a),0,1 ;; word aligned
  919. endm
  920. ;; ?aloc is the macro that actually allocates local storage.
  921. ;; it is only invoked by the localx macros.
  922. ;;
  923. ;; usage:
  924. ;; ?aloc n,t,l,s,a
  925. ;; where:
  926. ;; n is a list of names of local variable of the
  927. ;; given type.
  928. ;; t is the text string for the given variable
  929. ;; and is one of:
  930. ;; word ptr
  931. ;; dword ptr
  932. ;; byte ptr
  933. ;; or alternatively left blank for variable size
  934. ;; allocations (no implicit type).
  935. ;; l is the size of the variable in bytes
  936. ;; s is the internal type flag (size), and is one of:
  937. ;; word - 2
  938. ;; dword - 4
  939. ;; byte - 1
  940. ;; variable - 0
  941. ;; a is a flag indicating that word alignment is to be
  942. ;; forced for this type of item.
  943. ;;
  944. ;; NOTE: It is assumed that the stack is already aligned on a word
  945. ;; boundary when the cProc is invoked. The macros will guarantee
  946. ;; to allocate an even number of bytes on the stack to maintain
  947. ;; word alignment.
  948. ?aloc macro n,t,l,s,a
  949. if ?cpd ;;must be in a proc def
  950. .xcref
  951. irp x,<n> ;;generate symbol equates
  952. ???=???+l ;;update length of locals
  953. if a ;;if align, then force word alignment
  954. ???=((??? + 1) and 0fffeh)
  955. endif
  956. ?al1 x,<t>,%(???+?ia) ;;?ia will always be valid (0 or 2)
  957. .xcref ?t&&x
  958. ?t&&x=s ;;save size info
  959. endm
  960. .cref
  961. else
  962. ??error <locals "&n" declared outside procedure def>
  963. endif
  964. endm
  965. ;; ?al1 - allocate local, continued.
  966. ;;
  967. ;; ?al1 actually generates the text equate for the local variable.
  968. ;; The form of the text equate generated is more or less:
  969. ;;
  970. ;; name equ (type ptr [bp-?ia-nn])
  971. ;; or
  972. ;; name equ ([bp-?ia-nn])
  973. ;;
  974. ;; where:
  975. ;; ?ia is defined to be either zero, or is defined to be
  976. ;; the number of bytes between the saved BP and the first
  977. ;; local. ?ia is only applicable if the current cProc is
  978. ;; a windows far procedure or if parmRs have been
  979. ;; encountered. If not, the ?ia will be zero. since ?ia
  980. ;; is determinable prior to invoking this macro, it will be
  981. ;; added into the offset ("nn") passed to this macro
  982. ;;
  983. ;; usage:
  984. ;; ?al1 n,t,o
  985. ;; where:
  986. ;; n is the name for the text equate
  987. ;; t is the type of the equate
  988. ;; o is the offset of the equate
  989. ?al1 macro n,t,o
  990. n equ (t [bp-o])
  991. endm
  992. ;; ?gcc - get calling convention
  993. ;;
  994. ;; ?gcv sets the given symbol to the calling convention
  995. ;; to be used.
  996. ;;
  997. ;; usage:
  998. ;; ?gcc s,i,cc
  999. ;;
  1000. ;; where:
  1001. ;; s is the symbol to return the convention in
  1002. ;; s = 0 if 'C' calling convention
  1003. ;; s = 1 if PL/M (PASCAL) calling convention
  1004. ;; i is the initial value for s
  1005. ;; cc is the calling convention override, and may be one of
  1006. ;; C use 'C' convention
  1007. ;; PLM use PL/M calling convention
  1008. ;; PASCAL use PL/M calling convention
  1009. ?gcc macro s,i,cc
  1010. s = i ;;Set default calling convention
  1011. ifnb <cc>
  1012. ifidn <cc>,<C> ;;If overriding default
  1013. s=0 ;; 'C' calling convention
  1014. endif
  1015. ifidn <cc>,<PLM>
  1016. s=1 ;; PL/M calling convention
  1017. endif
  1018. ifidn <cc>,<PASCAL>
  1019. s=1 ;; PL/M calling convention
  1020. endif
  1021. endif
  1022. endm
  1023. ifndef ?NOGLOBAL
  1024. .xcref
  1025. .xcref globalB,globalW,globalD,globalQ,globalT,globalCP,globalDP
  1026. .cref
  1027. ;; globalx - define global data of type x
  1028. ;;
  1029. ;; usage:
  1030. ;; globalx n,i,s,c
  1031. ;; where:
  1032. ;; x is the type of the variable b=byte, w=word, d=dword
  1033. ;; q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
  1034. ;; n is the name to be given the variable.
  1035. ;; i is the initial value of the variable.
  1036. ;; s is the duplication factor
  1037. ;; c is the convention, C for C, PLM or PASCAL for PL/M.
  1038. ;; The default (?PLM flag) will be used if not specified.
  1039. ;;
  1040. ;; The D form will generate two extra equates of the form off_n and seg_n.
  1041. globalB macro n,i,s,c
  1042. ?ad <n>,1
  1043. ?dd n,1,<byte>,<db>,<i>,<s>,<c>
  1044. endm
  1045. globalW macro n,i,s,c
  1046. ?ad <n>,2
  1047. ?dd n,1,<word>,<dw>,<i>,<s>,<c>
  1048. endm
  1049. globalD macro n,i,s,c
  1050. ?ad <n>,4
  1051. ?dd n,1,<dword>,<dd>,<i>,<s>,<c>
  1052. off_&n equ n
  1053. seg_&n equ n[2]
  1054. endm
  1055. globalQ macro n,i,s,c
  1056. ?ad <n>,8
  1057. ?dd n,1,<qword>,<dq>,<i>,<s>,<c>
  1058. endm
  1059. globalT macro n,i,s,c
  1060. ?ad <n>,10
  1061. ?dd n,1,<tbyte>,<dt>,<i>,<s>,<c>
  1062. endm
  1063. if sizec
  1064. globalCP macro n,i,s,c
  1065. globalD n,<i>,<s>,<c>
  1066. endm
  1067. else
  1068. globalCP macro n,i,s,c
  1069. globalW n,<i>,<s>,<c>
  1070. endm
  1071. endif
  1072. if sized
  1073. globalDP macro n,i,s,c
  1074. globalD n,<i>,<s>,<c>
  1075. endm
  1076. else
  1077. globalDP macro n,i,s,c
  1078. globalW n,<i>,<s>,<c>
  1079. endm
  1080. endif
  1081. endif
  1082. ifndef ?NOSTATIC
  1083. .xcref
  1084. .xcref staticB,staticW,staticD,staticQ,staticT,staticCP,staticDP
  1085. .cref
  1086. ;; staticx - define static data of type x
  1087. ;;
  1088. ;; usage:
  1089. ;; staticx n,i,s
  1090. ;; where:
  1091. ;; x is the type of the variable b=byte, w=word, d=dword
  1092. ;; q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
  1093. ;; n is the name to be given the variable.
  1094. ;; i is the initial value of the variable.
  1095. ;; s is the duplication factor
  1096. ;;
  1097. ;; statics do not generate an underscored version of the symbol
  1098. ;; since they are intended to be internal symbols. If they are
  1099. ;; required to be public, use globlax.
  1100. staticB macro n,i,s
  1101. ?ad <n>,1
  1102. ?dd n,0,<byte>,<db>,<i>,<s>,<PLM> ;;PLM to keep from generating _
  1103. endm
  1104. staticW macro n,i,s
  1105. ?ad <n>,2
  1106. ?dd n,0,<word>,<dw>,<i>,<s>,<PLM>
  1107. endm
  1108. staticD macro n,i,s
  1109. ?ad <n>,4
  1110. ?dd n,0,<dword>,<dd>,<i>,<s>,<PLM>
  1111. endm
  1112. staticQ macro n,i,s
  1113. ?ad <n>,8
  1114. ?dd n,0,<qword>,<dq>,<i>,<s>,<PLM>
  1115. endm
  1116. staticT macro n,i,s
  1117. ?ad <n>,10
  1118. ?dd n,0,<tbyte>,<dt>,<i>,<s>,<PLM>
  1119. endm
  1120. if sizec
  1121. staticCP macro n,i,s
  1122. staticD n,<i>,<s>
  1123. endm
  1124. else
  1125. staticCP macro n,i,s
  1126. staticW n,<i>,<s>
  1127. endm
  1128. endif
  1129. if sized
  1130. staticDP macro n,i,s
  1131. staticD n,<i>,<s>
  1132. endm
  1133. else
  1134. staticDP macro n,i,s
  1135. staticW n,<i>,<s>
  1136. endm
  1137. endif
  1138. endif
  1139. ;; ?dd is the generalized data definition macro.
  1140. ;;
  1141. ;; format:
  1142. ;; ?dd n,p,t,d,i,s,c
  1143. ;; where:
  1144. ;; n is the name of the procedure
  1145. ;; p is the public flag
  1146. ;; t is the assembler type (byte, word, dword)
  1147. ;; d is the assembler directive (db,dw or dd)
  1148. ;; i is the initial value
  1149. ;; s is a duplication factor
  1150. ;; c is the convention, C for C, PLM or PSACAL for PL/M.
  1151. ;; The default (?PLM flag) will be used if not specified.
  1152. ?dd macro n,p,t,d,i,s,c
  1153. ?gcc ?dd2,%?PLM,<c> ;;Set calling convention
  1154. ife ?dd2 ;;If 'C'
  1155. n label t
  1156. ?dd1 _&n,p,<d>,<i>,<s> ;;Microsoft C uses leading underscores
  1157. else
  1158. ?dd1 n,p,<d>,<i>,<s> ;;If PL/M
  1159. endif
  1160. endm
  1161. ;; ?dd1 is the generalized data definition macro.
  1162. ;;
  1163. ;; format:
  1164. ;; ?dd1 n,p,d,i,s
  1165. ;; where:
  1166. ;; n is the name of the procedure
  1167. ;; p is the public flag
  1168. ;; d is the assembler directive (db,dw or dd)
  1169. ;; i is the initial value
  1170. ;; s is a duplication factor
  1171. ?dd1 macro n,p,d,i,s
  1172. if p
  1173. public n
  1174. endif
  1175. ifb <s>
  1176. n d i
  1177. else
  1178. ifb <i>
  1179. n d s dup (?)
  1180. else
  1181. n d s dup (i)
  1182. endif
  1183. endif
  1184. endm
  1185. ifndef ?NOEXTERN
  1186. .xcref
  1187. .xcref ?ex1,?ex2,externB,externW,externD,externQ,externT
  1188. .xcref externNP,externFP,externP,externCP,externDP,externA
  1189. .cref
  1190. ?ex2 = 0
  1191. ;; externx - define external data of type x
  1192. ;;
  1193. ;; usage:
  1194. ;; externx n,c
  1195. ;; where:
  1196. ;; x is the type of the variable b=byte, w=word, d=dword
  1197. ;; q=quad word, t=tenbytes, cp=code pointer
  1198. ;; dp=data pointer, a=absolute
  1199. ;; n is a list of names to define
  1200. ;; c is the convention, C for C, PLM or PSACAL forPL/M.
  1201. ;; The default (?PLM flag) will be used if not specified.
  1202. externA macro n,c ;;40h is reserved for whatever will
  1203. ?ex1 <n>,40h,<abs>,<c>,<> ;; be done in the future for ASB
  1204. endm ;; externals
  1205. externB macro n,c
  1206. ?ex1 <n>,1,<byte>,<c>,<>
  1207. endm
  1208. externW macro n,c
  1209. ?ex1 <n>,2,<word>,<c>,<>
  1210. endm
  1211. externD macro n,c
  1212. ?ex1 <n>,4,<dword>,<c>,<>
  1213. endm
  1214. externQ macro n,c
  1215. ?ex1 <n>,8,<qword>,<c>,<>
  1216. endm
  1217. externT macro n,c
  1218. ?ex1 <n>,10,<tbyte>,<c>,<>
  1219. endm
  1220. externNP macro n,c
  1221. ?ex1 <n>,2,<near>,<c>,<cc>
  1222. endm
  1223. externFP macro n,c
  1224. ?ex1 <n>,4,<far>,<c>,<cc>
  1225. endm
  1226. if sizec
  1227. externP macro n,c
  1228. ?ex1 <n>,4,<far>,<c>,<cc>
  1229. endm
  1230. else
  1231. externP macro n,c
  1232. ?ex1 <n>,2,<near>,<c>,<cc>
  1233. endm
  1234. endif
  1235. if sizec
  1236. externCP macro n,c
  1237. ?ex1 <n>,4,<dword>,<c>,<>
  1238. endm
  1239. else
  1240. externCP macro n,c
  1241. ?ex1 <n>,2,<word>,<c>,<>
  1242. endm
  1243. endif
  1244. if sized
  1245. externDP macro n,c
  1246. ?ex1 <n>,4,<dword>,<c>,<>
  1247. endm
  1248. else
  1249. externDP macro n,c
  1250. ?ex1 <n>,2,<word>,<c>,<>
  1251. endm
  1252. endif
  1253. ;; ?ex1 is the generalized external definition macro
  1254. ;;
  1255. ;; format:
  1256. ;; ?ex1 n,s,d,c,scv
  1257. ;; where:
  1258. ;; n is are the names of the externals
  1259. ;; s is the size in bytes (used for typing)
  1260. ;; d is the type
  1261. ;; c is the convention, C for C, PLM or PSACAL for PL/M.
  1262. ;; The default (?PLM flag) will be used if not specified.
  1263. ;; scv save calling convention. If this field is "cc", then
  1264. ;; the calling convention will be saved in a ?CCn equ.
  1265. ?ex1 macro n,s,d,c,scv
  1266. ?gcc ?ex2,%?PLM,<c>
  1267. irp x,<n>
  1268. .xcref
  1269. .xcref ?t&&x
  1270. .cref
  1271. ?t&&x=s ;;save size info
  1272. ife ?ex2
  1273. extrn _&&x:&d
  1274. x equ _&&x
  1275. else
  1276. extrn x:&d
  1277. endif
  1278. ifidn <scv>,<cc> ;;save calling convention (C or PL/M)
  1279. .xcref ;; if NP, FP, or P
  1280. .xcref ?CC&&x
  1281. .cref
  1282. ?CC&&x=?ex2
  1283. endif
  1284. endm
  1285. endm
  1286. endif
  1287. ifndef ?NOLABEL
  1288. .xcref
  1289. .xcref ?lb1,?lblpu,?lb2
  1290. .xcref labelB,labelW,labelD,labelQ,labelT
  1291. .xcref labelNP,labelFP,labelP,labelCP,labelDP
  1292. .cref
  1293. ?lblpu = 0
  1294. ?lb2 = 0
  1295. ;; labelx - define label of data type x
  1296. ;;
  1297. ;; usage:
  1298. ;; labelx n,c
  1299. ;; where:
  1300. ;; x is the type of the variable b=byte, w=word, d=dword
  1301. ;; q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
  1302. ;; n is a list of names to define, the first of which can
  1303. ;; be the keyword public
  1304. ;; c is the convention, C for C, PLM or PSACAL for PL/M.
  1305. ;; The default (?PLM flag) will be used if not specified.
  1306. labelB macro n,c
  1307. ?lb1 <n>,1,<byte>,<c>
  1308. endm
  1309. labelW macro n,c
  1310. ?lb1 <n>,2,<word>,<c>
  1311. endm
  1312. labelD macro n,c
  1313. ?lb1 <n>,4,<dword>,<c>
  1314. endm
  1315. labelQ macro n,c
  1316. ?lb1 <n>,8,<qword>,<c>
  1317. endm
  1318. labelT macro n,c
  1319. ?lb1 <n>,10,<tbyte>,<c>
  1320. endm
  1321. labelNP macro n,c
  1322. ?lb1 <n>,2,<near>,<c>
  1323. endm
  1324. labelFP macro n,c
  1325. ?lb1 <n>,4,<far>,<c>
  1326. endm
  1327. if sizec
  1328. labelP macro n,c
  1329. ?lb1 <n>,4,<far>,<c>
  1330. endm
  1331. else
  1332. labelP macro n,c
  1333. ?lb1 <n>,2,<near>,<c>
  1334. endm
  1335. endif
  1336. if sizec
  1337. labelCP macro n,c
  1338. ?lb1 <n>,4,<dword>,<c>
  1339. endm
  1340. else
  1341. labelCP macro n,c
  1342. ?lb1 <n>,2,<word>,<c>
  1343. endm
  1344. endif
  1345. if sized
  1346. labelDP macro n,c
  1347. ?lb1 <n>,4,<dword>,<c>
  1348. endm
  1349. else
  1350. labelDP macro n,c
  1351. ?lb1 <n>,2,<word>,<c>
  1352. endm
  1353. endif
  1354. ;; ?lb1 is the generalized label definition macro
  1355. ;;
  1356. ;; format:
  1357. ;; ?lb1 n,s,d
  1358. ;; where:
  1359. ;; n are the names of the labels
  1360. ;; s is the size in bytes (used for typing)
  1361. ;; d is the type
  1362. ;; c is the convention, C for C, PLM or PSACAL for PL/M.
  1363. ;; The default (?PLM flag) will be used if not specified.
  1364. ?lb1 macro n,s,d,c
  1365. ?gcc ?lb2,%?PLM,<c>
  1366. ?lblpu=0
  1367. irp x,<n>
  1368. ifidn <x>,<PUBLIC>
  1369. ?lblpu=1
  1370. else
  1371. .xcref
  1372. .xcref ?t&&x
  1373. .cref
  1374. ?t&&x=s ;;save size info
  1375. ife ?lb2 ;;If C
  1376. if ?lblpu
  1377. public _&&x
  1378. endif
  1379. _&&x label &d
  1380. x equ _&&x
  1381. else ;;If PL/M
  1382. if ?lblpu
  1383. public x
  1384. endif
  1385. x label &d
  1386. endif
  1387. endif
  1388. endm
  1389. endm
  1390. endif
  1391. ifndef ?NODEF
  1392. ;; defx - inform macros that name is of type x
  1393. ;;
  1394. ;; The given name(s) is flaged to be of the given type. This macro
  1395. ;; is intended for giving types to variables that were not generated
  1396. ;; by the macros (i.e., static storage). There must be a type definition
  1397. ;; for all parameters in a call list.
  1398. ;;
  1399. ;; usage:
  1400. ;; defx n
  1401. ;; where:
  1402. ;; x is the type of the variable b=byte, w=word, d=dword
  1403. ;; n is the name(s) to be given the variable(s).
  1404. ;;
  1405. ;; Bytes are considered to be two bytes long for alignment reasons
  1406. .xcref
  1407. .xcref defB,defW,defD,defQ,defT,defCP,defDP
  1408. .cref
  1409. defB macro n
  1410. ?ad <n>,1
  1411. endm
  1412. defW macro n
  1413. ?ad <n>,2
  1414. endm
  1415. defD macro n
  1416. ?ad <n>,4
  1417. endm
  1418. defQ macro n
  1419. ?ad <n>,8
  1420. endm
  1421. defT macro n
  1422. ?ad <n>,10
  1423. endm
  1424. if sizec
  1425. defCP macro n
  1426. defD <n>
  1427. endm
  1428. else
  1429. defCP macro n
  1430. defW <n>
  1431. endm
  1432. endif
  1433. if sized
  1434. defDP macro n
  1435. defD <n>
  1436. endm
  1437. else
  1438. defDP macro n
  1439. defW <n>
  1440. endm
  1441. endif
  1442. endif
  1443. ; ?ad is the macro which creates a definition for the given
  1444. ; symbol
  1445. ;
  1446. ; usage:
  1447. ; ?ad <n>,s
  1448. ; where:
  1449. ; n is a list of names to define
  1450. ; s is the size info (1,2,4,8,10)
  1451. ?ad macro n,s
  1452. irp x,<n>
  1453. .xcref
  1454. .xcref ?t&&x
  1455. .cref
  1456. ?t&&x=s ;;save size info
  1457. endm
  1458. endm
  1459. ifndef ?NOPTR
  1460. .xcref
  1461. .xcref regPtr,farPtr
  1462. .cref
  1463. ;; regPtr generates information allowing a 32-bit pointer currently
  1464. ;; in a register to be pushed as a parameter to a subroutine using
  1465. ;; the cCall macro.
  1466. ;;
  1467. ;; usage:
  1468. ;; regptr n,s,o
  1469. ;; where:
  1470. ;; n is the name the argument will be known as
  1471. ;; s is the register containing the segment portion
  1472. ;; of the pointer
  1473. ;; o is the register containing the offset portion
  1474. ;; of the pointer
  1475. ;;
  1476. ;; 2/14/85 - made obsolete with farptr
  1477. regPtr macro n,s,o
  1478. farPtr n,s,o
  1479. endm
  1480. ;; farPtr generates information allowing a 32-bit pointer to be
  1481. ;; pushed as a parameter to a subroutine using the cCall macro.
  1482. ;;
  1483. ;; usage:
  1484. ;; farptr n,s,o
  1485. ;; where:
  1486. ;; n is the name the argument will be known as
  1487. ;; s is the segment portion of the pointer
  1488. ;; o is the offset portion of the pointer
  1489. ;;
  1490. ;; Note that any cast must have been made in the argument itself
  1491. ;; (i.e. regptr ptr1,ds,<word ptr 3[si]>)
  1492. farPtr macro n,s,o
  1493. .xcref
  1494. .xcref ?t&n
  1495. .cref
  1496. n &macro
  1497. push s ;@
  1498. push o ;@
  1499. &endm
  1500. ?t&n=80h
  1501. endm
  1502. endif
  1503. ;; arg - declare argument
  1504. ;;
  1505. ;; The given argument(s) is added to the argument list structure
  1506. ;;
  1507. ;; format:
  1508. ;; arg a
  1509. ;;
  1510. ;; where:
  1511. ;; a is any valid argument to push.
  1512. ;;
  1513. ;; If any element in arglist has not been defined or isn't a 16-bit
  1514. ;; register, then a complete specification must have been given in a
  1515. ;; text equate and a defx also given (if not, you'll pay the penalty!)
  1516. arg macro a
  1517. irp x,<a>
  1518. ?argc=?argc+1 ;;increment the arg count
  1519. ?atal <x>,%?argc ;;generate argument
  1520. endm
  1521. endm
  1522. ;; ?atal (add to argument list) generates a macro that will cause
  1523. ;; the given argument to be processed when invoked. It is used by
  1524. ;; the arg macro only.
  1525. ?atal macro n,i
  1526. .xcref
  1527. .xcref ?ali&i
  1528. .cref
  1529. ?ali&i &macro
  1530. ?ap n
  1531. &endm
  1532. endm
  1533. ;; ?ap - process arguments and place onto stack
  1534. ;;
  1535. ;; The given argument is processed (type checking) and place on
  1536. ;; the stack for a pending call. There must be a type definition
  1537. ;; for all arguments (except words). This can be done by using
  1538. ;; text equates and the defx macro.
  1539. ;;
  1540. ;; format:
  1541. ;; ?ap n
  1542. ;; where:
  1543. ;; n is the name of the argument to be pushed
  1544. ;;
  1545. ;; The variable ?argl is updated by the length of the arguments
  1546. ;; pushed so that the stack can be cleaned up after the call.
  1547. ?ap macro n
  1548. ?argl=?argl+2 ;;assume one word is pushed
  1549. ifdef ?t&n
  1550. ife ?t&n-1 ;;byte type
  1551. push word ptr (n) ;@
  1552. exitm
  1553. endif
  1554. ife ?t&n-2 ;;word type
  1555. push n ;@
  1556. exitm
  1557. endif
  1558. ife ?t&n-4 ;;dword type
  1559. push word ptr (n)[2] ;@
  1560. push word ptr (n) ;@
  1561. ?argl=?argl+2
  1562. exitm
  1563. endif
  1564. ife ?t&n-8 ;;qword type
  1565. push word ptr (n)[6] ;@
  1566. push word ptr (n)[4] ;@
  1567. push word ptr (n)[2] ;@
  1568. push word ptr (n) ;@
  1569. ?argl=?argl+6
  1570. exitm
  1571. endif
  1572. if ?t&n and 80h ;;far pointer type
  1573. n
  1574. ?argl=?argl+2
  1575. exitm
  1576. endif
  1577. ife ?t&n ;;variable storage
  1578. push word ptr (n) ;@
  1579. exitm
  1580. endif
  1581. endif
  1582. push n ;;unknown or register or immediate ;@
  1583. endm
  1584. ;; cCall - call a 'c' language procedure
  1585. ;;
  1586. ;; The given procedure is called with the given parameters.
  1587. ;; If the calling convention is C, the arguments are pushed
  1588. ;; in reverse order, and removed after the called procedure
  1589. ;; returns. If the calling conventing is PL/M, the arguments
  1590. ;; are pushed as they were encountered, and the called procedure
  1591. ;; is assumed to have removed them from the stack.
  1592. ;;
  1593. ;; The calling convention priority will be:
  1594. ;; 1) that specified on the cCall if present
  1595. ;; 2) that defined by the target
  1596. ;; 3) the default (?PLM flag)
  1597. ;;
  1598. ;; format:
  1599. ;; ccall n,<a>,c
  1600. ;;
  1601. ;; where:
  1602. ;; n is the name of the procedure to call
  1603. ;; a are arguments to be pushed (optional, may be
  1604. ;; specified with the "arg" macro.
  1605. ;; c is the convention, C for C, PLM or PSACAL for PL/M.
  1606. ;; The default (?PLM flag) will be used if not specified.
  1607. cCall macro n,a,c
  1608. ifnb <a> ;;add any arguments to list
  1609. arg <a>
  1610. endif
  1611. mpush %?rsl ;;save registers (if any)
  1612. ifdef ?CC&n ;;if calling convention has been
  1613. ?cCall1=?CC&n ;; defined for target, use it
  1614. else ;;else use the default
  1615. ?cCall1=?PLM
  1616. endif
  1617. ifnb <c> ;;If possible override, check it out
  1618. ?gcc ?cCall1,%?cCall1,<c>
  1619. endif
  1620. ?argl=0 ;;init argument length
  1621. ife ?cCall1 ;;if C calling convention
  1622. ?acb=?argc ;;initialize for looping
  1623. else
  1624. ?acb=1 ;;initialize for looping
  1625. endif
  1626. rept ?argc ;;push arguments and purge macros
  1627. uconcat <?ali>,%?acb
  1628. uconcat <purge>,,<?ali>,%?acb
  1629. ife ?cCall1 ;;if C calling convention
  1630. ?acb=?acb-1
  1631. else
  1632. ?acb=?acb+1
  1633. endif
  1634. endm
  1635. call n ;;call the procedure ;@
  1636. if ((?cCall1 eq 0) and (?argl ne 0)) ;;If C calling convention and arguments
  1637. add sp,?argl ;; then remove them ;@
  1638. endif
  1639. mpop %?rsl ;;pop all specified regs
  1640. ?rsl=0 ;;invalidate save list
  1641. ?argc= 0 ;; " arguments
  1642. ?argl= 0
  1643. endm
  1644. ;; cProc - define a 'c' procedure
  1645. ;;
  1646. ;; cProc is the procedure definition for procedures.
  1647. ;;
  1648. ;; format:
  1649. ;; cProc n,cf,a
  1650. ;; where:
  1651. ;; n is the name of the procedure
  1652. ;;
  1653. ;; cf controls certain definitions, and may be:
  1654. ;; NEAR proc is to be a near label
  1655. ;; FAR proc is to be a far label
  1656. ;; PUBLIC proc is to be defined as public
  1657. ;; SMALL call makeframe procedure
  1658. ;; NODATA dont create prolog code to setup DS
  1659. ;; ATOMIC don't link stack if not needed
  1660. ;; NODATA must be specified for ATOMIC
  1661. ;; FORCEFRAME Force generation of a frame
  1662. ;; NOTE: FORCEFRAME no longer supported
  1663. ;; C proc is to be a C procedure
  1664. ;; PLM proc is to be a PL/M procedure
  1665. ;; PASCAL proc is to be a PL/M procedure
  1666. ;; WIN proc is to be a windows procedure
  1667. ;; NONWIN proc isn't to be a windows procedure
  1668. ;; LOADDS Preserve & set DS to _DATA
  1669. ;; EXPORTED mov ax,ds, nop at start of routine
  1670. ;;
  1671. ;; a is a list of registers that are to be saved whenever
  1672. ;; the procedure is invoked.
  1673. ;;
  1674. ;; makeframe procedure: If small is specified, then
  1675. ;; the "makeframe procedure" is invoked instead of
  1676. ;; generating normal prologues/epilogues
  1677. ;;
  1678. ;; A call is performed to the makeframe procedure. The
  1679. ;; call is followed by two bytes. the first byte is the
  1680. ;; number of locals to allocate for the frame, the second
  1681. ;; is the number of bytes of parameters. The makeframe
  1682. ;; procedure will in turn call the cProc routine at the
  1683. ;; address following the data bytes. When the cProc is
  1684. ;; finished, it will do a near return to the makeframe
  1685. ;; procedure to clean up the frame and exit.
  1686. ;;
  1687. ;; Note that register parameters and makeframe are
  1688. ;; incompatible and cannot be used together.
  1689. ;;
  1690. ;; The makeframe procedure will save SI, DI, and also
  1691. ;; DS if a far procedure. These registers will be
  1692. ;; removed from the autosave list if specified.
  1693. cProc macro n,cf,a
  1694. if ?cpd
  1695. ?utpe ;;generate unterminated proc error
  1696. endif
  1697. ?cpd=1 ;;a procdef is active now
  1698. ???=0 ;;no locals are defined yet
  1699. ?argc=0 ;;no arguments are defined
  1700. ?ba=0 ;;not in a procedure
  1701. ?po=0 ;;initial parameter offset
  1702. ?pu=0 ;;initial public setting
  1703. ?ia=0 ;;no special prolog/epilog
  1704. ?adj=4 ;;parameter adjustment (near ret+bp)
  1705. ?rp=0 ;;no register parameters
  1706. ?uf=0 ;;don't use makeframe
  1707. ?wfp=?WIN ;;default far procedure (win or not)
  1708. ?ff=0 ;;don't force frame setup
  1709. ?pas=0 ;;process register save list
  1710. ?pcc=?PLM ;;calling convention (C or PL/M)
  1711. ?lds=0 ;;no LOADDS
  1712. ?exp=0 ;;not EXPORTED
  1713. ifnb <a> ;;register save list
  1714. ?ri ?pas,<a>
  1715. endif
  1716. ?pc=sizec ;;default size
  1717. ?nd=?nodata1 ;;default NODATA flag
  1718. ?nx=0 ;;default is not ATOMIC
  1719. irp x,<cf>
  1720. ifidn <x>,<FAR> ;;if far,
  1721. ?pc=1 ;; set far flag
  1722. endif
  1723. ifidn <x>,<NEAR> ;;if near,
  1724. ?pc=0 ;; set near flag
  1725. endif
  1726. ifidn <x>,<PUBLIC> ;;if public,
  1727. ?pu=1 ;; set public flag
  1728. endif
  1729. ifidn <x>,<SMALL> ;;if small
  1730. ?uf=1 ;; set small flag
  1731. endif
  1732. ifidn <x>,<DATA> ;;if data
  1733. ?nd=0 ;; reset NODATA flag
  1734. endif
  1735. ifidn <x>,<NODATA> ;;if NODATA
  1736. ?nd=1 ;; set NODATA flag
  1737. endif
  1738. ifidn <x>,<ATOMIC> ;;if ATOMIC
  1739. ?nx=1 ;; set ATOMIC flag
  1740. endif
  1741. ifidn <x>,<C> ;;if to force C calling convention
  1742. ?pcc=0 ;; set flag
  1743. endif
  1744. ifidn <x>,<PLM> ;;if to force PLM calling convention
  1745. ?pcc=1 ;; set flag
  1746. endif
  1747. ifidn <x>,<PASCAL> ;;if to force PLM calling convention
  1748. ?pcc=1 ;; set flag
  1749. endif
  1750. ifidn <x>,<WIN> ;;if to force a Window's frame
  1751. ?wfp=1 ;; set flag
  1752. endif
  1753. ifidn <x>,<NONWIN> ;;if not to be a Window's frame
  1754. ?wfp=0 ;; set flag
  1755. endif
  1756. ifidn <x>,<LOADDS> ;; Preserve & setup DS
  1757. ?lds=1
  1758. endif
  1759. ifidn <x>,<EXPORTED>
  1760. ?exp=1
  1761. endif
  1762. endm
  1763. if ?pcc ;;If PLM
  1764. ?PLMPrevParm=0 ;; show no previous parameter
  1765. .xcref
  1766. .xcref ?PLMParm0
  1767. .cref
  1768. ?PLMParm0 &macro ;;Null macro to terminate
  1769. purge ?PLMParm0
  1770. &endm
  1771. endif
  1772. .xcref
  1773. .xcref ?CC&n
  1774. .cref
  1775. ?CC&n=?pcc ;;Save procedure type
  1776. if (?nx eq 1) and (?nd eq 0) ;;ATOMIC requires NODATA
  1777. ?nx = 0 ;;clear the ATOMIC keyword
  1778. ??error <ATOMIC specified without NODATA - ATOMIC ignored>
  1779. endif
  1780. if ?pc ;;if a far procedure
  1781. if ?wfp+?exp+?lds ;;if windows, EXPORTED, or LOADDS
  1782. ife ?nx ;;and not ATOMIC
  1783. ife ?pmd ;;If PMODE, no adjustment needed
  1784. ?ia=2 ;; adjust locals for saved ds
  1785. endif
  1786. ?pas = ?pas and (not ?ds) ;;no need for extra save
  1787. endif
  1788. endif
  1789. ?adj=?adj+2 ;;far, make parameter adjustment
  1790. else
  1791. ?wfp=0 ;;not a far windows procedure
  1792. endif
  1793. ife ?386regs
  1794. ?pas = ?pas and (not (?sp+?cs+?ss)) ;;make no sense to save these
  1795. endif
  1796. if ?uf ;;don't save these if user frame
  1797. if ?386regs
  1798. ?pas = ?pas and (not (?si+?di))
  1799. else
  1800. ?pas = ?pas and (not (?bp+?si+?di))
  1801. endif
  1802. endif
  1803. ife ?pcc
  1804. ?pg <_&n>,%?pu,%?pc,%?pas,%?wfp,<n>,%?pcc
  1805. else
  1806. ?pg <n>,%?pu,%?pc,%?pas,%?wfp,<n>,%?pcc
  1807. endif
  1808. endm
  1809. ;; ?pg - generate begin and nested macros for current procedure
  1810. ;;
  1811. ;; format:
  1812. ;; ?pg n,p,c,a,w,nnu,cc
  1813. ;; where:
  1814. ;; n is the name of the procedure
  1815. ;; p is the public flag
  1816. ;; c is the class definition for the procedure
  1817. ;; a is an enumerated list of registers to save
  1818. ;; at entry and restore at exit
  1819. ;; w true if a far windows procedure
  1820. ;; nnu procedure name without any underscore
  1821. ;; cc calling convention (C or PL/M)
  1822. ;;
  1823. ;;
  1824. ;; local stack allocation will be forced to an even byte count to
  1825. ;; maintain stack word alignment.
  1826. ;;
  1827. ;;
  1828. ?pg macro n,p,c,a,w,nnu,cc
  1829. .xcref
  1830. if ?uf ;;if user frame
  1831. if ?nd
  1832. ??error <NODATA encountered in &n - user frame ignored>
  1833. ?uf=0
  1834. endif
  1835. endif
  1836. .xcref cBegin
  1837. cBegin &macro g ;;generate cBegin macro
  1838. .xcref
  1839. if cc ;;Finish definition of parameters
  1840. uconcat <?PLMParm>,%?PLMPrevParm,%?po
  1841. endif
  1842. if ?uf ;;if user frame
  1843. if ?rp
  1844. ??error <parmR encountered in &n - user frame ignored>
  1845. ?uf=0
  1846. endif
  1847. endif
  1848. ?pg1 <n>,c,a,%?po,w,%?uf,%?nd,%?rp,cc ;;generate cEnd macro
  1849. ?cpd=0 ;;terminate current proc def
  1850. ?argc=0 ;;no arguments are defined yet
  1851. ?ba=1 ;;have reached a begin
  1852. ???=(???+1) and 0fffeh ;;word align local storage
  1853. if p ;;If to be public
  1854. public n
  1855. endif
  1856. ife c ;;declare procedure type
  1857. n proc near
  1858. else
  1859. n proc far
  1860. endif
  1861. ife cc ;;if 'C' calling convention
  1862. nnu equ n ;; generate label without underscore
  1863. endif
  1864. ifidn <g>,<nogen> ;;if nogen specified, shouldn't have
  1865. if ???+?po+a+?rp ;; parms, locals, or saved regs
  1866. ??_out <cBegin - possible invalid use of nogen>
  1867. endif
  1868. else ;;must generate a frame
  1869. if ?uf ;;if user frame code specified
  1870. ?mf c,%???,%?po ;; call user's makeframe
  1871. mpush a ;; save specified registers
  1872. else
  1873. if w+?exp+?lds ;;if a far windows procedure
  1874. if ?pmd ;;if protect mode:
  1875. ife ?nd ;; if not NODATA
  1876. if ?lds ;; and LOADDS
  1877. mov ax,_DATA ;; ax = _DATA
  1878. else ;; else if EXPORTED
  1879. if ?exp
  1880. mov ax,ds ;; ax = DS
  1881. nop ;;
  1882. endif
  1883. endif
  1884. endif
  1885. ife ?nx ;;!ATOMIC:
  1886. if ???+?po ;; or there are no locals or params
  1887. if ?chkstk1 ;; if stack checking,
  1888. push bp ;; we can't use ENTER
  1889. mov bp,sp
  1890. else
  1891. if ??? ;; If there are locals, use ENTER
  1892. enter ???,0
  1893. else
  1894. push bp ;; otherwise it's smaller/faster
  1895. mov bp,sp ;; to use standard sequence
  1896. endif
  1897. endif
  1898. endif
  1899. push ds ;; preserve DS
  1900. if ?lds+?exp ;; if LOADDS or EXPORTED
  1901. mov ds,ax ;; set up new DS
  1902. endif
  1903. else ;;ATOMIC:
  1904. if ?ff+???+?po+?rp ;;if any locals or parameters
  1905. push bp ;; then must set frame pointer ;@
  1906. mov bp,sp ;; to be able to access them ;@
  1907. endif
  1908. endif
  1909. else ;; !?pmd
  1910. ife ?nd ;;if not NODATA,
  1911. mov ax,ds ;; then set AX = currentds, and ;@
  1912. nop ;; leave room for MOV AX,_DATA ;@
  1913. endif
  1914. ife ?nx ;;if not ATOMIC, far frame must be set
  1915. ife ?DOS5 ;;if not DOS5, then set far frame flag
  1916. inc bp ;; by incrementing the old bp ;@
  1917. endif
  1918. push bp ;@
  1919. mov bp,sp ;@
  1920. push ds ;@
  1921. else ;;ATOMIC procedure
  1922. if ?ff+???+?po+?rp ;;if any locals or parameters
  1923. push bp ;; then must set frame pointer ;@
  1924. mov bp,sp ;; to be able to access them ;@
  1925. endif
  1926. endif
  1927. ife ?nd ;;if not NODATA, then AX should
  1928. mov ds,ax ;; have the ds to use ;@
  1929. endif
  1930. endif ;; !?pmd
  1931. else ;;not windows. use standard prolog
  1932. if ?pmd ;;protect mode:
  1933. if ?exp
  1934. mov ax,ds ;; If EXPORTED, generate patchable
  1935. nop ;; instruction.
  1936. else
  1937. if ?lds ;; If LOADDS, set up AX = _DATA
  1938. mov ax,_DATA
  1939. endif
  1940. endif
  1941. if ?ff+???+?po+?rp ;; If frame needed...
  1942. if ?chkstk1 ;; if stack checking,
  1943. push bp ;; we can't use ENTER
  1944. mov bp,sp
  1945. else
  1946. if ??? ;; If there are locals, use ENTER
  1947. enter ???,0
  1948. else
  1949. push bp ;; otherwise it's smaller/faster
  1950. mov bp,sp ;; to use standard sequence
  1951. endif
  1952. endif
  1953. endif
  1954. if ?exp+?lds ;;if EXPORTED or LOADDS
  1955. push ds ;; preserve DS
  1956. mov ds,ax ;; and set up new one.
  1957. endif
  1958. else ;; ! ?pmd
  1959. if ?ff+???+?po+?rp ;;if any locals or parameters
  1960. push bp ;; then must set frame pointer ;@
  1961. mov bp,sp ;; to be able to access them ;@
  1962. endif
  1963. endif ;; ! ?pmd
  1964. endif ;; ! w
  1965. if ?rp ;;if parmR's, push them before
  1966. ?uf=0 ;; allocating locals and saving
  1967. rept ?rp ;; the autosave registers
  1968. uconcat mpush,,?rp,%?uf
  1969. ?uf=?uf+1
  1970. endm
  1971. endif
  1972. if ??? ;;if locals to allocate
  1973. if ?chkstk1 ;;if stack checking enabled
  1974. ifdef ?CHKSTKPROC ;;if user supplied stack checking
  1975. ?CHKSTKPROC %??? ;; invoke it with bytes requested
  1976. else
  1977. mov ax,??? ;;invoke default stack checking ;@
  1978. ife cc
  1979. call _chkstk ;@
  1980. else
  1981. call chkstk ;@
  1982. endif
  1983. endif
  1984. else ;;no stack checking
  1985. ife ?pmd ;;no need if in pmode (we used enter)
  1986. sub sp,??? ;; allocate any local storage ;@
  1987. endif
  1988. endif
  1989. endif
  1990. mpush a ;;save autosave registers
  1991. endif
  1992. ifdef ?PROFILE ;;if profiling enabled
  1993. if c ;; and a far procedure
  1994. call StartNMeas ;; invoke profile start procedure ;@
  1995. endif
  1996. endif
  1997. endif
  1998. .cref
  1999. purge cBegin ;;remove the macro
  2000. &endm ;;end of cBegin macro
  2001. .xcref ?utpe
  2002. ?utpe &macro
  2003. ??error <unterminated procedure definition: "&n">
  2004. &endm
  2005. .cref
  2006. endm ;;end of ?pg macro
  2007. ;; ?pg1 - generate end macro for current procedure
  2008. ;;
  2009. ;; format:
  2010. ;; ?pg1 n,c,a,o,w,f,d,r,cc
  2011. ;; where:
  2012. ;; n is the name of the procedure
  2013. ;; c is the class definition for the procedure
  2014. ;; a is an enumerated list of registers to save
  2015. ;; at entry and restore at exit
  2016. ;; o is the number of bytes of paramteres to remove at exit
  2017. ;; w true if a far windows procedure
  2018. ;; f is 1 if to use the user's makeframe procedure
  2019. ;; d is 1 if NODATA procedure
  2020. ;; r number of register parameters
  2021. ;; cc calling convention (C or PL/M)
  2022. ?pg1 macro n,c,a,o,w,f,d,r,cc
  2023. .xcref
  2024. .xcref cEnd
  2025. cEnd &macro g ;;start of cEnd macro
  2026. .xcref
  2027. ?ba=0 ;;no longer in a procedure
  2028. ifidn <g>,<nogen> ;;validate nogen usage
  2029. if o+a+r
  2030. ??_out <cEnd - possible invalid use of nogen>
  2031. endif
  2032. else ;;must generate an epilog
  2033. ifdef ?PROFILE ;;if profiling enabled
  2034. if c ;; and a far procedure
  2035. call StopNMeas ;; invoke profile stop procedure
  2036. endif ;; (doesn't trash DX:AX)
  2037. endif
  2038. mpop a ;;restore autosaved registers
  2039. if f ;;if to use the "makeframe" procedure
  2040. db 0c3h ;; near return to user's makeframe @
  2041. else
  2042. if w+?exp+?lds ;;if far win proc, use special epilog
  2043. if ?pmd
  2044. ife ?nx
  2045. pop ds ;; if not ATOMIC, restore DS
  2046. endif
  2047. ife ?nx ;; if not ATOMIC and no locals
  2048. if ?chkstk1+???+?po
  2049. leave
  2050. endif
  2051. else ;;ATOMIC:
  2052. if ?ff+???+?po+?rp ;;if any parameters
  2053. leave ;; fix up BP & exit
  2054. endif
  2055. endif
  2056. else ;; !?pmd
  2057. ife ?nx ;;if not ATOMIC, bp was pushed
  2058. if (?TF eq 0) or (???+?rp) ;;if cannot assume valid sp
  2059. lea sp,-2[bp] ;; or locals or parmR's, get valid SP @
  2060. endif
  2061. pop ds ;;restore saved ds and bp @
  2062. pop bp ;; @
  2063. ife ?DOS5 ;;if not DOS5, bp was
  2064. dec bp ;; incremented to mark far frame @
  2065. endif
  2066. else ;;ATOMIC frame was set up
  2067. if (?TF eq 0) or (???+?rp) ;;if cannot assume valid sp
  2068. mov sp,bp ;; or locals or parmR's, get valid SP @
  2069. endif
  2070. if ???+?po+?rp
  2071. pop bp ;@
  2072. endif
  2073. endif
  2074. endif ;; !?pmd
  2075. else ;;non-windows standard epilog
  2076. if ?pmd
  2077. if ?ff+???+?po+?rp ;;if any parameters
  2078. leave
  2079. endif
  2080. else
  2081. if ?ff+???+?po+?rp ;;if any parameters
  2082. if (?TF eq 0) or (???+?rp) ;;if cannot assume valid SP
  2083. mov sp,bp ;; or locals or parmR's, get valid SP;@
  2084. endif
  2085. pop bp ;@
  2086. endif
  2087. endif
  2088. endif
  2089. ife cc ;;if C calling convention
  2090. ret ;; return ;@
  2091. else ;;else
  2092. ret o ;; return and remove paramteres ;@
  2093. endif
  2094. endif
  2095. endif
  2096. n endp ;;end of process
  2097. .cref
  2098. purge cEnd ;;remove the macro
  2099. &endm
  2100. .cref
  2101. endm
  2102. ; assumes is a macro that will set up the assumes for a segment
  2103. ; or group created with the createSeg macro. If the assumed
  2104. ; value passed in isn't known, then a normal assume is made.
  2105. ;
  2106. ; usage:
  2107. ; assumes s,g
  2108. ;
  2109. ; where:
  2110. ; s is the register to make the assumption about
  2111. ; g is the value to assume is in it
  2112. assumes macro s,ln
  2113. ifndef ln&_assumes
  2114. assume s:ln
  2115. else
  2116. ln&_assumes s
  2117. endif
  2118. endm
  2119. ; createSeg is a macro that sets up a segment definition and
  2120. ; a logical name for that segment. The logical name can be
  2121. ; used to enter the segment, but it cannot be used for anything
  2122. ; else.
  2123. ;
  2124. ; usage:
  2125. ; createSeg n,ln,a,co,cl,grp
  2126. ; where:
  2127. ; n is the physical name of the segment
  2128. ; ln is the name it is to be invoked by
  2129. ; a is the alignment, and is optional
  2130. ; co is the combine type, and is optional
  2131. ; cl is the class, and is optional
  2132. ; grp is the name of the group that contains this segment
  2133. createSeg macro n,ln,a,co,cl,grp
  2134. ifnb <grp>
  2135. addseg grp,n
  2136. else
  2137. ln&OFFSET equ offset n:
  2138. ln&BASE equ n
  2139. ?cs3 <ln>,<n>
  2140. endif
  2141. ifnb <cl>
  2142. n segment a co '&cl'
  2143. else
  2144. n segment a co
  2145. endif
  2146. n ends
  2147. ?cs1 <ln>,<n>
  2148. endm
  2149. addseg macro grp,seg
  2150. .xcref
  2151. .xcref grp&_def
  2152. .cref
  2153. ifndef grp&_def
  2154. grp&_def=0
  2155. endif
  2156. if grp&_def ne ASMpass
  2157. .xcref
  2158. .xcref grp&_add
  2159. .cref
  2160. grp&_add &macro s
  2161. grp&_in <seg>,s
  2162. &endm
  2163. .xcref
  2164. .xcref grp&_in
  2165. .cref
  2166. grp&_in &macro sl,s
  2167. ifb <s>
  2168. grp group sl
  2169. else
  2170. grp&_add &macro ns
  2171. grp&_in <sl,s>,ns
  2172. &endm
  2173. endif
  2174. &endm
  2175. grp&_def=ASMpass
  2176. else
  2177. grp&_add seg
  2178. endif
  2179. endm
  2180. defgrp macro grp,ln
  2181. addseg grp
  2182. ifnb <ln>
  2183. irp x,<ln>
  2184. ?cs3 <&x>,<grp>
  2185. x&&OFFSET equ offset grp:
  2186. x&&BASE equ grp
  2187. endm
  2188. endif
  2189. endm
  2190. ?cs1 macro ln,n
  2191. .xcref
  2192. .xcref ln&_sbegin
  2193. .cref
  2194. ln&_sbegin &macro
  2195. .xcref
  2196. .xcref ?mf
  2197. .cref
  2198. ?mf &&macro c,l,p ;;when sBegin is invoked, generate
  2199. if c ;; the makeframe macro
  2200. extrn n&_FARFRAME:near ;; make frame for far procedures ;@
  2201. call n&_FARFRAME ;@
  2202. else
  2203. extrn n&_NEARFRAME:near ;; make frame for near procedures ;@
  2204. call n&_NEARFRAME ;@
  2205. endif
  2206. db l shr 1 ;;define number of locals ;@
  2207. db p shr 1 ;;define number of parameters ;@
  2208. &&endm
  2209. ?cs2 <ln>,<n>
  2210. n segment
  2211. &endm
  2212. endm
  2213. ?cs2 macro ln,n
  2214. .xcref
  2215. .xcref sEnd
  2216. .cref
  2217. sEnd &macro
  2218. n ends
  2219. purge ?mf ;;delete the makeframe macro
  2220. purge sEnd
  2221. &endm
  2222. endm
  2223. ?cs3 macro ln,n
  2224. .xcref
  2225. .xcref ln&_assumes
  2226. .cref
  2227. ln&_assumes &macro s
  2228. assume s:&n
  2229. &endm
  2230. endm
  2231. ; sBegin is the macro that opens up the definition of a segment.
  2232. ; The segment must have already been defined with the createSeg
  2233. ; macro.
  2234. ;
  2235. ; usage:
  2236. ; sBegin ln
  2237. ;
  2238. ; where:
  2239. ; ln is the logical name given to the segment when
  2240. ; it was declared.
  2241. .xcref
  2242. .xcref sBegin
  2243. .cref
  2244. sBegin macro ln
  2245. ln&_sbegin
  2246. endm
  2247. ife ?DF
  2248. ; Define all segments that will be used. This will allow the
  2249. ; assume and groups to be set up at one given place, and also
  2250. ; allow quick changes to be made
  2251. ;
  2252. ; createSeg name,logname,align,combine,class,group
  2253. createSeg _TEXT,Code,word,public,CODE
  2254. ife ?nodata1
  2255. createSeg _DATA,Data,word,public,DATA,DGROUP
  2256. defgrp DGROUP,Data
  2257. endif
  2258. if ?chkstk1
  2259. ifndef ?CHKSTKPROC
  2260. externp <chkstk>
  2261. endif
  2262. endif
  2263. endif
  2264. ; errnz exp - generate error message if expression isn't zero
  2265. ;
  2266. ; The errnz will generate an error message if the expression "exp"
  2267. ; does not evaluate to zero. This macro is very useful for testing
  2268. ; relationships between items, labels, and data that was coded into
  2269. ; an application.
  2270. ;
  2271. ; errnz <offset $ - offset label> ;error if not at "label"
  2272. ; errnz <eofflag and 00000001b> ;eofflag must be bit 0
  2273. ;
  2274. ; For expressions involving more than one token, the angle brackets
  2275. ; must be used.
  2276. ;
  2277. ; The macro is only evaluated on pass 2, so forward references may be
  2278. ; used in the expression.
  2279. errnz macro x ;;display error if expression is <>0
  2280. if2
  2281. if x ;;if expression is non-zero,
  2282. errnz1 <x>,%(x)
  2283. endif
  2284. endif
  2285. endm
  2286. errnz1 macro x1,x2
  2287. = *errnz* x1 = x2
  2288. .err
  2289. endm
  2290. ; errn$ label,exp - generate error message if label (exp) <> $
  2291. ;
  2292. ; The errnz will generate an error message if the label and "exp"
  2293. ; does not evaluate to the current value of the location counter.
  2294. ; This macro is very useful for testing relationships between
  2295. ; labels and the location counter that was coded into an application.
  2296. ;
  2297. ; examples: errn$ label ;error if not at "label"
  2298. ; errn$ label,+3 ;error if not three bytes from "label"
  2299. ; errn$ label,-3 ;error if not three bytes past "label"
  2300. ;
  2301. ; If no "exp" is given, it is the same as specifying 0
  2302. ;
  2303. ; The macro is only evaluated on pass 2, so forward references may be
  2304. ; used in the expression.
  2305. errn$ macro l,x ;;error if <$-label1 (exp2)> <>0
  2306. errnz <offset $ - offset l x>
  2307. endm
  2308. ;; If profile has been specified, declare the profile routines
  2309. ;; to be external and far. It would be best if this could be done
  2310. ;; when the call is actually made, but then the fix-up would be
  2311. ;; generated as segment-relative.
  2312. ifdef ?PROFILE
  2313. externFP <StartNMeas,StopNMeas>
  2314. endif