home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l231 / 3.ddi / INCLUDE / CMACROS.IN$ / CMACROS
Encoding:
Text File  |  1992-10-01  |  44.4 KB  |  2,026 lines

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