home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / macros / macros.asm next >
Encoding:
Assembly Source File  |  1997-08-07  |  26.9 KB  |  913 lines

  1.  
  2. ;*************************************************
  3. ;** Macros                                      **
  4. ;** © 1990,93,96 THOR-Software inc.             **
  5. ;** Version 1.17 23th July 1996                 **
  6. ;**---------------------------------------------**
  7. ;** This is a package of useful macros for the  **
  8. ;** DevPac assembler                            **
  9. ;** feel free to strip the comments             **
  10. ;** but leave every comments marked with an     **
  11. ;** asterisk (*) because they are printed       **
  12. ;** as error messages if something's getting    **
  13. ;** wrong                                       **
  14. ;*************************************************
  15.  
  16.  
  17. ;*************************************************
  18. ;** Global arguments                            **
  19. ;**---------------------------------------------**
  20. ;** If you define a label named                 **
  21. ;** SHORTSTACK                                  **
  22. ;** the stack gets only word aligned instead of **
  23. ;** long aligned.                               **
  24. ;** This takes less stack space, but slows the  **
  25. ;** code for the MC'20 and higher processors    **
  26. ;** somewhat down.                              **
  27. ;*************************************************
  28.  
  29.  
  30. ;*************************************************
  31. ;** Some useful macros for modifying the        **
  32. ;** condition codes in 6502 style               **
  33. ;*************************************************
  34.  
  35. sec     Macro           ;set carry
  36.         ori #$01,ccr
  37.         Endm
  38.         
  39. clc     Macro           ;clear carry
  40.         andi #$fe,ccr
  41.         Endm
  42.         
  43. sez     Macro           ;set zero
  44.         ori #$04,ccr
  45.         Endm
  46.         
  47. clz     Macro           ;clear zero
  48.         andi #$fb,ccr
  49.         Endm
  50.         
  51. sen     Macro           ;set negative
  52.         ori #$08,ccr
  53.         Endm
  54.         
  55. cln     Macro           ;clear negative
  56.         andi #$f7,ccr
  57.         Endm
  58.  
  59. noz     Macro           ;invert zero
  60.         eor #$04,ccr
  61.         EndM
  62.  
  63. sev     Macro           ;set overflow
  64.         ori #$02,ccr
  65.         Endm
  66.         
  67. clv     Macro           ;clear overflow
  68.         andi #$fd,ccr
  69.         Endm
  70.         
  71. clx     Macro           ;clear X
  72.         andi #$ef,ccr
  73.         Endm
  74.  
  75. sex     Macro           ;set X
  76.         ori #$10,ccr
  77.         EndM
  78.  
  79. ;*************************************************
  80. ;** the next lines clear internal counters      **
  81. ;** do not touch them                           **
  82. ;*************************************************
  83.         
  84. _sc     set 0           ;the stack counter
  85. _rc     set 0           ;counter for registers
  86. _re     set 0           ;level counter for registers
  87. _fc     set 0           ;counter for loops
  88. _fe     set 0           ;level counter for loops
  89. _pc     set 0           ;parameter counter for C style functions
  90. _pe     set 0           ;level counter for C style functions
  91. _pm     set 0           ;counts removed parameters
  92. _bs     set 0           ;space taken by global static variables
  93.  
  94. ;*************************************************
  95. ;** some macros for stack management            **
  96. ;** mainly internal use                         **
  97. ;** but also register framing                   **
  98. ;*************************************************
  99.  
  100.         ifd __G2        ;this works only for DevPac 2 and better
  101.  
  102. reserve Macro           ;reserve room on the stack
  103.         iflt \1
  104.                 fail    ;(*) argument must be greater than zero
  105.                 mexit
  106.         endc
  107.         
  108.         ifd SHORTSTACK
  109. _si\<_sc> set (\1+((\1)&1))
  110.         elseif
  111. _si\<_sc> set ((\1+3)&-4)
  112.         endc
  113.         
  114.         ifne \1
  115.                 ifle _si\<_sc>-8
  116.                         subq.l #_si\<_sc>,a7
  117.                 elseif
  118.                         lea -_si\<_sc>(a7),a7
  119.                 endc
  120.         endc
  121. _sc     set _sc+1
  122.         Endm
  123.  
  124. ;Example:
  125. ;       reserve 100
  126. ;       Reserve 100 bytes of stack space, relative to a7.
  127. ;       address it with dist(a7), dist is positive
  128. ;
  129.         
  130. restore Macro           ;restore stack space
  131.         ifle _sc
  132.                 fail    ;(*) illegal nesting
  133.                 mexit   
  134.         endc
  135. _sc     set _sc-1
  136.         ifne _si\<_sc>
  137.                 ifle _si\<_sc>-8
  138.                          addq.l #_si\<_sc>,a7
  139.                 elseif
  140.                         lea _si\<_sc>(a7),a7
  141.                 endc
  142.         endc
  143.         EndM
  144.  
  145. ;Example:
  146. ;       reserve 100             reserve stack space
  147. ;        ....
  148. ;       restore                 restore stack
  149. ;
  150. ;       reserve and restore nest, btw
  151.         
  152.  
  153. extend Macro            ;Extend the memory allocated with "reserve" by n bytes
  154.         ifle _sc
  155.                 fail
  156.                 mexit   ;(*) nest failure: "reserve" missing
  157.         endc
  158.         
  159.         ifd SHORTSTACK
  160. _si\<_sc> set (\1+((\1)&1))
  161.         elseif
  162. _si\<_sc> set ((\1+3)&-4)
  163.         endc
  164.         
  165.         ifle _si\<_sc>-8
  166.                 subq.l #_si\<_sc>,a7
  167.         elseif
  168.                 lea -_si\<_sc>(a7),a7
  169.         endc
  170. _sh     set _sc-1
  171. _si\<_sh> set _si\<_sh>+_si\<_sc>
  172.         EndM
  173.  
  174. ;Example:
  175. ;               reserve 100     allocate 100 bytes
  176. ;               extend  50      allocate another 50 bytes in the same stack frame, so get 150
  177. ;               restore         give 100+50 bytes back
  178.         
  179.  
  180. shrink Macro            ;shrink the stack space by n bytes, opposide to extend
  181.         ifle _sc
  182.                 fail    ;(*) nest failure: reserve missing
  183.                 mexit
  184.         endc
  185.         
  186.         ifd SHORTSTACK
  187. _si\<_sc> set (\1+((\1)&1))
  188.         elseif
  189. _si\<_sc> set ((\1+3)&-4)
  190.         endc
  191.         
  192.         ifle _si\<_sc>-8
  193.                 addq.l #_si\<_sc>,a7
  194.         elseif
  195.                 lea _si\<_sc>(a7),a7
  196.         endc
  197. _sh     set _sc-1
  198. _si\<_sh> set _si\<_sh>-_si\<_sc>
  199.         iflt _si\<_sh>
  200.                 fail    ;(*) shrink out of range
  201.                 mexit
  202.         endc
  203.         EndM
  204. ;Example:
  205. ;               reserve 100     reserve 100 bytes
  206. ;               extend 50       get another 50 bytes in the same frame
  207. ;               shrink 75       give 75 bytes back
  208. ;               restore         give the remaining 75 bytes back
  209.  
  210.         
  211. _lastget Macro                  ;internal macro for stack relative addressing
  212.         ifne _sh-_sc
  213. _sj     set _sj+_si\<_sh>
  214. _sh     set _sh+1
  215.         _lastget
  216.         endc
  217.         EndM
  218.         
  219. loadbase Macro                  ;get base address of a previously loaded stack frame
  220.         iflt \1
  221.                 fail    ;(*) out of range
  222.                 mexit
  223.         endc
  224. _sh     set _sc-\1
  225.         iflt _sh
  226.                 fail    ;(*) nest failure: reserve missing
  227.                 mexit
  228.         endc
  229. _sj     set 0
  230.         _lastget
  231.         lea _sj(a7),\2
  232.         EndM
  233.  
  234. ;Example:
  235. ;               reserve 100
  236. ;                reserve 50
  237. ;                loadbase 1,a6  load base address of the first stack frame into a6
  238. ;                               a6 is now relative to the 100 bytes,
  239. ;                               a7 to the 50 bytes
  240. ;                restore
  241. ;               restore         give everything back
  242.  
  243.         
  244. saveregs Macro                  ;save registers to the stack
  245. _rc     set _rc+1               ;unique id
  246. _re     set _re+1               ;counts levels
  247. _rn\<_re> set _rc               ;level->number
  248. _ri\<_rc> reg \1
  249.         movem.l \1,-(sp)
  250.         EndM
  251.  
  252. ;Example:
  253. ;               saveregs d2-d3/a2-a3/a6
  254. ;
  255. ;               Unlike the usual macros, this call DOES nest!
  256. ;
  257. ;
  258.         
  259. loadregs Macro                  ;load macros from the stack
  260.         ifle _re
  261.                 fail            ;(*) nest failure: saveregs missing
  262.                 mexit
  263.         endc
  264. _rt     set _rn\<_re>
  265.         movem.l (sp)+,_ri\<_rt>
  266. _re     set _re-1
  267.         EndM
  268.  
  269. ;Example:
  270. ;               saveregs d2-d3/a2-a3/a6
  271. ;                ...
  272. ;                saveregs d2-d4         yes, this NESTS!
  273. ;                ...
  274. ;                loadregs               reload the first set
  275. ;                ...
  276. ;               loadregs                reload the second set
  277.  
  278.  
  279. ;*************************************************
  280. ;** Automatic loop support                      **
  281. ;** do/while loops & for/next loops             **
  282. ;*************************************************
  283.  
  284. for     Macro           ;a popular for next loop, counts downwards in words
  285. _fc     set _fc+1       ;unique id
  286. _fe     set _fe+1       ;level counter
  287. _fn\<_fe> set _fc       ;level to number
  288.         ifc '','\1'                     ;without parameters
  289.                 bra.\0 ._fi\<_fc>_loop
  290.         elseif
  291.                 move.\0 \1-1,\2         ;(*) only immediate adressing
  292.         endc
  293. ._fi\<_fc>_do:
  294.         EndM
  295.  
  296. ;Examples
  297. ;       for             start of the loop, counter already loaded
  298. ;                       zero is a legal counter value, the body isn't
  299. ;                       executed then
  300. ;       for.s           start of the loop, short loop, counter already loaded
  301. ;
  302. ;       for.l #9,d0     start loop, load counter (9 loops here)
  303. ;                       this one gets optimized (one branch less)
  304. ;                       but allows only immediate addressing to
  305. ;                       load the counter register (d0 here)
  306. ;
  307.         
  308. next    Macro           ;end of the loop
  309.         ifle _fe
  310.                 fail    ;(*) nest failure: for missing
  311.                 mexit
  312.         endc
  313. _ft     set _fn\<_fe>
  314. ._fi\<_ft>_loop:
  315.         ifc '','\1'
  316.                 fail    ;(*) counter register missing
  317.                 mexit
  318.         endc
  319.         ifc '','\2'
  320. ._fi\<_ft>_cont:
  321.                 dbra \1,._fi\<_ft>_do
  322.         elseif          ;(*) cont invalid with condition
  323.                 db\1 \2,._fi\<_ft>_do
  324.         endc
  325. ._fi\<_ft>_exit:
  326. _fe     set _fe-1
  327.         EndM
  328.         
  329. ;Examples
  330. ;       next d0         end of a for loop with counter register d0
  331. ;       next eq,d0      end of a loop, terminate the loop if eq OR
  332. ;                       counted down to zero
  333. ;
  334. ;Full example:
  335. ;       for.l #12,d0
  336. ;        clr.l (a0)+
  337. ;       next d0         clears 12 adjacent long words
  338. ;                       all labels are generated by the macro set
  339. ;
  340. ;       remember, all this looping stuff NESTS!
  341.  
  342. break   Macro           ;terminates a for or do loop immediately, jumps behind the final comand
  343.         ifle _fe        
  344.                 fail    ;(*) break not in a loop body
  345.                 mexit
  346.         endc
  347. _ft     set _fn\<_fe>
  348.         ifc '','\1'     ;without condition
  349.                 bra.\0 ._fi\<_ft>_exit
  350.         elseif
  351.                 b\1.\0 ._fi\<_ft>_exit
  352.         endc
  353.         EndM
  354.  
  355. ;Examples
  356. ;       for.l #9,d0
  357. ;        ...
  358. ;        break          terminate loop now
  359. ;
  360. ;       next d0
  361. ;
  362. ;       break.s         break, short distances
  363. ;       break.s eq      break if the eq flag is set
  364. ;
  365.  
  366. cont    Macro           ;continue with the next iteration
  367.         ifle _fe        
  368.                 fail    ;(*) cont not in a loop body
  369.                 mexit
  370.         endc
  371. _ft     set _fn\<_fe>
  372.         ifc '','\1'     ;without condition
  373.                 bra.\0 ._fi\<_ft>_cont          ;(*) cont impossible with next & condition
  374.         elseif
  375.                 b\1.\0 ._fi\<_ft>_cont          ;(*) cont impossible with next & condition
  376.         endc
  377.         EndM
  378.  
  379. ;Examples
  380. ;
  381. ;       for.l #8,d0
  382. ;        ...
  383. ;        cont.s eq              next iteration if Z flag is set
  384. ;        ...
  385. ;       next d0                 end of loop
  386. ;
  387.  
  388. reloop  Macro                   ;redo looping
  389.         ifle _fe        
  390.                 fail            ;(*) reloop not in a loop body
  391.                 mexit
  392.         endc
  393. _ft     set _fn\<_fe>
  394.         ifc '','\1'     ;without condition
  395.                 bra.\0 ._fi\<_ft>_do
  396.         elseif
  397.                 b\1.\0 ._fi\<_ft>_do
  398.         endc
  399.         EndM
  400.  
  401. ;Examples
  402. ;
  403. ;       reloop          rerun this iteration
  404. ;       reloop.s        rerun, short jump
  405. ;       reloop.s cc     rerun if the carry flag is cleared
  406. ;
  407. ;       The difference between reloop and cont is that cont starts
  408. ;       the next iteration of a loop (so, the counter is decremented)
  409. ;       while reloops reruns the loop again with the old counter
  410. ;       there is NO difference between reloop and cont for do/while
  411. ;       style loops
  412.  
  413.  
  414. do      Macro           ;start of a loop, execute it at least once
  415. _fc     set _fc+1       ;increment id
  416. _fe     set _fe+1       ;level counter
  417. _fn\<_fe> set _fc       ;level->number
  418. ._fi\<_fc>_do:
  419. ._fi\<_fc>_cont:
  420.         EndM
  421.  
  422.  
  423. repeat  Macro           ;start a loop, possibly no execution at all
  424. _fc     set _fc+1       ;increment id
  425. _fe     set _fe+1       ;level counter
  426. _fn\<_fe> set _fc       ;level->number
  427.         bra.\0 ._fi\<_fc>_loop  ;jump to the end of the loop
  428. ._fi\<_fc>_do:
  429. ._fi\<_fc>_cont:
  430.         EndM
  431.         
  432. while   Macro           ;end of a loop
  433.         ifle _fe
  434.                 fail    ;(*) nest failure: No loop started
  435.                 mexit
  436.         endc
  437. _ft     set _fn\<_fe>
  438. ._fi\<_ft>_loop:
  439.         b\1.\0 ._fi\<_ft>_do
  440. ._fi\<_ft>_exit:
  441. _fe     set _fe-1       
  442.         EndM
  443.  
  444. loop    Macro
  445.         while.\0 ra
  446.         EndM
  447.  
  448. ;Examples:
  449. ;       do              start a loop....
  450. ;        ...
  451. ;       while.s eq      as long as the Z flag is set, short loop
  452. ;
  453. ;Full example: Travese an exec style list
  454. ;
  455. ;       lea lh_Head(a2),a0      ;get head node
  456. ;       do
  457. ;        move.l (a0),a0         ;get first node
  458. ;        tst.l (a0)             ;test if this is a real node or the end
  459. ;        break.s eq             ;abort if end of list reached
  460. ;
  461. ;        ...                    ;do something with the node
  462. ;       loop.s                  ;continue operation
  463. ;
  464. ;
  465. ;       repeat.s                ;short jump
  466. ;       ...
  467. ;       while.s eq              ;quite the same as the first example
  468. ;                               ;but checks the condition first before
  469. ;                               ;the loop is entered. A set Z flag
  470. ;                               ;will never enter the loop
  471.  
  472.  
  473. ;*************************************************
  474. ;** String macros                               **
  475. ;** implementations of some standard C functions**
  476. ;*************************************************
  477.  
  478. smove   Macro                   ;copy one string to another, like strcpy
  479.         ifne NARG-2
  480.                 fail            ;(*) only two arguments
  481.         endc
  482.         
  483. ._sm\@: move.b (\1)+,(\2)+
  484.         bne.s ._sm\@
  485.         EndM    
  486.  
  487. ;Examples
  488. ;       smove a0,a1             ;copy string *a0 to string *a1
  489. ;
  490.  
  491.  
  492. strlen  Macro                   ;get the length of a string, excluding the NUL
  493.         ifne NARG-2
  494.                 fail            ;(*) only two arguments
  495.                 mexit
  496.         endc
  497.         move.l \1,\2
  498. ._sl\@:
  499.         tst.b (\1)+
  500.         bne.s ._sl\@
  501.         sub.l \1,\2
  502.         not.l \2
  503.         Endm
  504.  
  505. ;Examples
  506. ;       strlen a0,d0            ;get the length of the string *a0 is
  507. ;                               ;pointing to and store it in d0
  508. ;                               ;*a0 points afterwards behind the NUL
  509. ;                               ;byte
  510.  
  511.  
  512. ;*************************************************
  513. ;** Calling C style functions with              **
  514. ;** arguments on the stack                      **
  515. ;*************************************************
  516.  
  517. _putarg Macro                   ;internal use macro, writes one argument
  518.         ifgt \1
  519. _pm             set 1           ;get one parameter
  520.  
  521.                 ifnc '','\2'
  522.                                                 ;hier: parameter present
  523.                         ifc '.l','\2'
  524. _pm                             set 2           ;explicit size: longword
  525. _pc                             set _pc+4
  526.                         endc
  527.                         ifc '.w','\2'
  528. _pm                             set 2           ;explicit size: word
  529. _pc                             set _pc+2
  530.                         endc
  531.                         ifc '.b','\2'
  532. _pm                             set 2           ;explicit size: byte
  533. _pc                             set _pc+2       ;a byte takes REALLY two bytes of stack!
  534.                         endc
  535.                         
  536.                         ifeq _pm-2
  537.                                 ifc '\3',''
  538.                                         fail    ;parameter missing
  539.                                         mexit
  540.                                 endc
  541.                                 move\2 \3,-(sp) ;write it to the stack
  542.                         elseif  
  543.                                 ifne _fl
  544.                                         move.l \2,-(sp) ;default long
  545. _pc                                     set _pc+4
  546.                                 elseif
  547.                                         move.w \2,-(sp) ;default word
  548. _pc                                     set _pc+2
  549.                                 endc
  550.                         endc
  551.         
  552.                 endc
  553.         
  554. _pe             set \1-_pm              ;now call this stuff recursively
  555.                 ifeq _pm-2
  556.                         _putarg \<_pe>,\4,\5,\6,\7,\8,\9,\A,\B,\C,\D,\E,\F,\G,\H,\I,\J
  557.                 elseif
  558.                         _putarg \<_pe>,\3,\4,\5,\6,\7,\8,\9,\A,\B,\C,\D,\E,\F,\G,\H,\I,\J
  559.                 endc
  560.         
  561.         endc
  562.         endm
  563.         
  564.         
  565. bcr     Macro                   ;call a C style function, use BSR
  566. _pc     set 0
  567. _fl     set 0
  568.         _putarg 18,\J,\I,\H,\G,\F,\E,\D,\C,\B,\A,\9,\8,\7,\6,\5,\4,\3,\2
  569.         bsr.\0 \1
  570.         ifne _pc
  571.         lea _pc(a7),a7
  572.         endc
  573.         EndM
  574.  
  575. jcr     Macro                   ;call a C style function, use JSR
  576. _pc     set 0
  577. _fl     set 0
  578.         _putarg 18,\J,\I,\H,\G,\F,\E,\D,\C,\B,\A,\9,\8,\7,\6,\5,\4,\3,\2
  579.         jsr \1
  580.         ifne _pc
  581.         lea _pc(a7),a7
  582.         endc
  583.         EndM
  584.  
  585. jtags   Macro                   ;a tag based library call with the tags as arguments
  586. _pc     set 4
  587. _fl     set 1
  588.         clr.l -(a7)             ;TAG_END
  589.         _putarg 17,\J,\I,\H,\G,\F,\E,\D,\C,\B,\A,\9,\8,\7,\6,\5,\4,\3
  590.         move.l a7,\2
  591.         jsr \1
  592.         lea _pc(a7),a7
  593.         EndM
  594.  
  595. ;Examples:
  596. ;       jcr Handler,.l,#0,IO(a1)
  597. ;       call the handler functions with long arguments,
  598. ;       zero and the contents of IO(a1)
  599. ;       put these arguments on the stack and free the stack
  600. ;       afterwards
  601. ;
  602. ;       bcr.s TempFree,.l,a1,a5,.b,#0,.l,ExecBase
  603. ;       call the TempFree function with long arguments a1,a5
  604. ;       one byte argument #0 and a long argument ExecBase
  605. ;
  606. ;       all sizes default to word except for the tag based calls,
  607. ;       where the size defaults to long.
  608. ;       types must be given PRIOR to the arguments
  609.  
  610.  
  611. ;*************************************************
  612. ;** More tag call support                       **
  613. ;** (different style)                           **
  614. ;*************************************************
  615.  
  616. deftag  Macro                   ;start of a tag call
  617. _pc     set 4
  618.         clr.l -(a7)             ;TAG_END
  619.         EndM
  620.         
  621. tag     Macro                   ;place a tag on the stack
  622.         move.l \2,-(sp)         ;(*) illegal tag data
  623.         move.l #\1,-(sp)        ;(*) illegal tag
  624. _pc     set _pc+8
  625.         EndM
  626.  
  627. itag    Macro                   ;place an indirect tag on the stack
  628.         move.l \2,-(sp)         ;(*) illegal tag data
  629.         move.l \1,-(sp)         ;(*) illegal tag
  630. _pc     set _pc+8
  631.         EndM
  632.         
  633. endtag  Macro                   ;end of a tag call and the call itself
  634.         move.l a7,\2
  635.         jsr \1
  636.         lea _pc(a7),a7
  637.         endM
  638.  
  639. ;Examples:
  640. ;       deftag
  641. ;        tag TAG_Width,#320
  642. ;        tag TAG_Height,#200
  643. ;       endtag OpenWindwoTagList(a6),a0
  644. ;
  645. ;       the first paratemter to the tag macro is the type of the
  646. ;       tag, the second its value.
  647. ;       The endtag macro takes two arguments as well, the
  648. ;       tag function and the parameter where the tag list has to
  649. ;       be provided
  650. ;
  651. ;       The tag call expects an immediate number as its first parameter
  652. ;       whereas the itag call accepts any legal data, so registers are
  653. ;       valid here, too.
  654.  
  655.  
  656. ;*************************************************
  657. ;** More macros for C-style functions           **
  658. ;** this time the function header itself        **
  659. ;*************************************************
  660.  
  661. defarg  Macro           ;start of the argument description
  662.         rsreset
  663. _sh     set 0
  664. _sj     set 0
  665.         _lastget
  666.         rs.l 1          ;reserve one long for the PC
  667.         ifnc '','\1'
  668.         rs.l \1         ;supply number of saved registers here
  669.         endc    
  670.         rs.b _sj        ;room reserved for auto variables
  671.         EndM
  672.         
  673. arg     Macro           ;get the name of one argument
  674.         ifc '','\0'
  675. \1              rs.w 1
  676.         elseif
  677. \1              rs.\0 1
  678.                 ifc 'b','\0'
  679.                         rs.b 1
  680.                 endc
  681.         endc
  682.         EndM
  683.         
  684. endarg  Macro           ;end of the argument list
  685.         EndM    
  686.  
  687. ;Examples for argument descriptions
  688. ;       saveregs d2-d3/a2
  689. ;       defarg 3        start of the arguments, three registers saved
  690. ;        arg buffer     one word, gets the name buffer
  691. ;        arg.l code     one longword
  692. ;        arg.w len      one word
  693. ;        arg.b char     one byte
  694. ;       endarg
  695. ;
  696. ;       move.l code(a7),d0      get the argument
  697. ;
  698.  
  699. ;*************************************************
  700. ;** The next one is pretty handy:               **
  701. ;** variable definions for assembly language    **
  702. ;** in case you run out of registers            **
  703. ;** the variables are taken from the stack      **
  704. ;** and require the stack macros from above     **
  705. ;*************************************************
  706.  
  707. defvar  Macro           ;start of the variable list
  708.         rsreset
  709.         EndM
  710.  
  711. auto    Macro           ;define one auto (stack) variable, take it from the stack
  712.         ifc     '','\2'
  713. \1              rs.\0   1
  714.         elseif
  715. \1              rs.\0   \2
  716.         endc
  717.         EndM
  718.         
  719. static  Macro           ;define a static (BSS) variable
  720.         ifc     '','\2'
  721. _bc             set 1
  722.         elseif
  723. _bc             set \2
  724.         endc
  725. _bz     set 0
  726.         ifc     'l','\0'
  727. _bs     set (_bs+1)&$fffffffe
  728. _bz             set 4
  729.         endc
  730.         ifc     'w','\0'
  731. _bs     set (_bs+1)&$fffffffe
  732. _bz             set 2
  733.         endc
  734.         ifc     'b','\0'
  735. _bz             set 1
  736.         endc
  737.         ifeq    _bz
  738.                 fail    ;(*) illegal data size
  739.                 mexit
  740.         endc
  741. \1      =_bs
  742. _bs     set     _bs+(_bc*_bz)
  743.         EndM
  744.         
  745. extern  Macro           ;define an external variable
  746.         xref    \1
  747.         EndM
  748.  
  749. register Macro          ;define a register variable
  750. \1      equr    \2
  751.         EndM
  752.  
  753. endvar  Macro           ;end of the variable list
  754. ._vl\@  rs.b 0
  755.         reserve ._vl\@
  756.         EndM
  757.         
  758. freevar Macro           ;free stack space allocated by variables
  759.         restore
  760.         EndM
  761.  
  762. staticspace Macro
  763.         ds.b _bs        ;reserve space for static variables
  764.         EndM            ;should be called only once in the program
  765.                         ;or you're wasting space
  766.  
  767. ;One example definition of a function that uses auto variables
  768. ;Foo:
  769. ;       saveregs d2-d3/a2       save local registers
  770. ;       defvar                  start of variable definitions
  771. ;        auto.w count           ;a counter
  772. ;        auto.l help,4          ;four longs
  773. ;        auto.b char            ;one character
  774. ;        auto.l inc             ;one long
  775. ;        static.l save          ;one static variable
  776. ;        register.w cinc,d0     ;a register variable
  777. ;       endvar                  ;that's it!
  778. ;
  779. ;       move.l d0,inc(a7)       ;set the inc-variable
  780. ;       move.w d1,count(a7)     ;set count
  781. ;       do
  782. ;        ...
  783. ;        add.l inc(a7),d2       ;increment d2
  784. ;       while.s cc              ;as long as no overflow
  785. ;       ...
  786. ;       freevar                 ;free variables
  787. ;       loadregs                ;get registers
  788. ;       rts
  789. ;
  790. ; One note: Variable names are (sorry to say that, but such is life)
  791. ; GLOBAL to the module. You've to invent some unique names for
  792. ; them. A popular choice is to use a shortcut of the procedure name
  793. ; and an underscore, like "foo_inc" instead of "inc"
  794.  
  795.         endc            ;the remaining stuff is valid for all assemblers
  796.  
  797. ;*************************************************
  798. ;** longword bit field addressing               **
  799. ;** for adress-register indirect                **
  800. ;** maybe very special, but I need them         **
  801. ;*************************************************
  802. btstm   Macro                   ;test one bit in a longword
  803.         btst #(\1)&$7,(3^((\1)>>3))+\2
  804.         Endm
  805.         
  806. bclrm   Macro                   ;clear one bit in a longword
  807.         bclr #(\1)&$7,(3^((\1)>>3))+\2
  808.         Endm    
  809.         
  810. bsetm   Macro                   ;set one bit in a longword
  811.         bset #(\1)&$7,(3^((\1)>>3))+\2
  812.         Endm    
  813.         
  814. bchgm   Macro                   ;change one bit in a longword
  815.         bchg #(\1)&$7,(3^((\1)>>3))+\2
  816.         Endm
  817.  
  818. bnegm   Macro                   ;like btstm, but returns the inverted result
  819.         btst #(\1)&$7,(3^((\1)>>3))+\2
  820.         noz
  821.         Endm    
  822.  
  823. ;Examples:
  824. ;               btstm cn_Test,cn_Flags(a5)
  825. ;               test the bit named "cn_Test" in the long word bit field
  826. ;               cn_Flags(a5)
  827. ;               The MSB of byte 0 is bit 31, the LSB of byte 3 is bit 0
  828. ;
  829.  
  830. ;*************************************************
  831. ;** List support macros                         **
  832. ;** partially stolen from exec/nodes.i          **
  833. ;*************************************************
  834.  
  835. NewList         Macro   ;Initialize a list. Much shorter than a function call
  836.         move.l \1,8(\1)
  837.         addq.l #4,\1
  838.         clr.l (\1)
  839.         move.l \1,-(\1)
  840.         endm
  841. ;provide an address register as argument that points to the list structure
  842.  
  843. ;The next macros take the same arguments as the exec functions of the
  844. ;same names, so mostly *a1 for the node pointer and *a0 for the
  845. ;list pointer. There's currently no way of using other registers
  846. ;even though the modification would be trivial
  847.  
  848. AddHead         Macro           ;add node *a1 to the top of list *a0
  849.         MOVE.L  (A0),D0
  850.         MOVE.L  A1,(A0)
  851.         MOVEM.L D0/A0,(A1)
  852.         MOVE.L  D0,A0
  853.         MOVE.L  A1,4(A0)
  854.         ENDM
  855.  
  856. AddTail         Macro           ;add node *a1 at the end of list *a0
  857.         ADDQ.L  #4,A0
  858.         MOVE.L  4(A0),D0
  859.         MOVE.L  A1,4(A0)
  860.         EXG     D0,A0
  861.         MOVEM.L D0/A0,(A1)
  862.         MOVE.L  A1,(A0)
  863.         ENDM
  864.  
  865. Remove          Macro           ;remove node *a1 from a list
  866.         MOVE.L  (A1)+,A0
  867.         MOVE.L  (A1),A1
  868.         MOVE.L  A0,(A1)
  869.         MOVE.L  A1,4(A0)
  870.         ENDM
  871.  
  872. RemHead         Macro           ;remove the head of a list, return ptr in d0
  873.         MOVE.L  (A0),A1
  874.         MOVE.L  (A1),D0
  875.         BEQ.S   .__remhead\@
  876.         MOVE.L  D0,(A0)
  877.         EXG.L   D0,A1
  878.         MOVE.L  A0,4(A1)
  879. .__remhead\@:
  880.         ENDM
  881.  
  882.  
  883. RemTail         Macro           ;remove the tail of a list, return ptr in d0
  884.         MOVE.L  8(A0),A1
  885.         MOVE.L  4(A1),D0
  886.         BEQ.S   .__remtail\@
  887.         MOVE.L  D0,8(A0)
  888.         EXG.L   D0,A1
  889.         MOVE.L  A0,(A1)
  890.         ADDQ.L  #4,(A1)
  891. .__remtail\@:
  892.         ENDM
  893.  
  894.  
  895. InsertAfter     Macro           ;insert node *a1 behind node *a0, no special cases, *a0 must be a valid node
  896.         move.l (a0),d0
  897.         movem.l d0/a0,(a1)
  898.         move.l a1,(a0)
  899.         move.l d0,a0
  900.         move.l a1,4(a0)
  901.         EndM
  902.  
  903. InsertBefore    Macro           ;insert node *a1 in front of *a0, no special cases, *a0 must be a valid node
  904.         move.l 4(a0),d0
  905.         move.l a1,4(a0)
  906.         exg.l a0,d0
  907.         movem.l d0/a0,(a1)
  908.         move.l a1,(a0)
  909.         EndM
  910.  
  911. ;That's all folks!
  912.  
  913.