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.

2450 lines
62 KiB

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