------------------------------------------------------------------------------

                                   PreFargo


                            by David Khling 1998

------------------------------------------------------------------------------


  =======================================
      Contents
  =======================================

    1. Introduction
    2. Usage
    3. PreFargo's Functionality
       1. Simple Operations
       2. Macros and Equates
          1. Macros
             1. IMPORTANT
          2. Equates
       3. Include Files
       4. Conditional Assembling
          1. #ifdef
          2. #ifndef
          3. #else
          4. #endif
          5. #error
       5. Local Symbols
    4. Suggestions
    5. End


  =======================================
      1. Introduction
  =======================================

PreFargo is a very powerful precompiler for the Fargo assembler, or any other
programming language. It's features are:

        * C-like comments: /* ... */ and //...
        * Spaces and Tabulators after commas are removed. This enables you
          to write e.g. `move.w      d0, d1' instead of `move.w     d0,d1'.
        * Filename and linenumbers are concatenated to every precompiled
          line. This will make it easier, to locate assembler errors.
        * C-like macros, e.g:
            #define x y
            #undef x
            #define f(x) y x y
            #define f(x) {
              y
              x
              y
            }
            #define f(x,ellipse...) y x y f(ellipse)
        * Equates: #equ x y
        * Include files (that are also PreFargo precompiled):
            #include <file>
            #include "file"
        * Conditional assembling, by #ifdef, #ifndef, #else, #endif and
          #error.
        * Local symbols, e.g:
            #local a,b,c
              ...
            #endlocal


  =======================================
      2. Usage
  =======================================

Normally you will just use `Prefargo.bat', to precompile and assemble your
programms. `Prefargo.bat' works almost like `Fargo.bat', but it expects you
to pass it a file, that ends on `.s' instead on `.asm'. `Prefargo.bat' will
just precompile the `.s' - file to an `.asm' - file, and pass the `.asm' file
to Fargo.bat. If you want to do this somehow else, you can get a summary on
the command line options of PreComp.exe, by executing it without arguments.


  =======================================
      3. PreFargo's Functionality
  =======================================

This section contains detailed explanations of all PreFargo's features.


 ---------------------------------------
     3. 1. Simple Operations
 ---------------------------------------

PreFargo won't copy any comment to the destination file. Valid comments are:

        * Comments, that are surrounded by `/*' and `*/', e.g.:

               /* simple comment */

               /**
                * multi line comment
                */

          You can even nest this kind of comment:

               /*
                    move.w d0, d1 /* d1.w = d0.w */
               */

        * Comments, that are introduced by '//' or ';', that extend to the
          end of line, e.g.:

               // This is a C++ - like comment

               ; This is a normal asm comment

PreFargo also does a lot other formatings on your programm. It replaces one
ore more Spaces or Tabulators by one Tabulator, and it removes Spaces and
Tabulators after commas. It is smart enough, to don't do these operations
within strings. Multi linebreaks are removed, too. Thereby assembling will
be speed up a little bit, and you can use some extended syntax, e.g:

        move.w  d0, d1

instead of:

        move.w  d0,d1   ; I hate this crushed style!

When PreFargo reaches the end of line, it will concatenate the filename and
linenumber to it, such as `;file(number)'. This will help you to locate
errors, that were output by the a68k assembler.

If there are passages within your programm, that you don't want to be
precompiled, you can surround them by `{' and `}'. PreFargo will also
consider nested '{...}' blocks. But for the reason, that it doesn't
precompile them, it won't recognize comment-tokens. That's why you shouldn't
comment out braces.

PreFargo also removes '|'. So this character does nothing. But it can be
used as separator, e.g. to separate a word from a macro, that should be
extracted (e.g.: In `WordMacro' `Macro' won't be recognized as extra word.
but `Word|Macro' is separated during reading, so `Macro' will be recoginzed).


 ---------------------------------------
     3. 2. Macros and Equates
 ---------------------------------------

  3.2.1 Macros
 --------------

PreFargo supports C-like macros. These macros are quite different to a68k's
macros. The syntax of macro declarations is the following:

        #define MacroName MacroContent

This will make PreFargo to replace `MacroName' in the rest of the program
by `MacroContent'. (Strings, comments etc. excluded). Macro names may
consist of numbers, letters, `_', `@', ':' and '.'. So you should even be
able to macros with numbers as name (e.g.: #define 0 $0)

You can also declare macros with arguments:

        #define MacorName(arg1,arg2,arg3) MacroContent

Thereby PreFargo will replace every appearanced of `MacroName(x,y,z)' by
`MacroContent', with replacing `arg1', `arg2' and `arg3' within MacroContent
by `x', `y' and `z'. For example:

        #define push_long(argument) move.l argument, -(a7)

        push_long(d0)   /* this is replaced by:

                                move.l d0, -(a7)
                        */

You can even declare macros with a variable number of arguments:

        #define define_bytes(arguments...) dc.b arguments

        define_bytes(0, 1, 2) /* this is replaced by:

                                  dc.b 0, 1, 2
                              */

`arguments...' just declares `argument' to be an ellipse. This means, that
all following arguments are put into it. You can use this feature, to
declare recursing macros, for example:

        #define push_reversed_words(arg1,remainder...) {

                #ifdef remainder
                  push_reversed_words(remainder)
                #endif

                move.w  arg1, -(a7)
        }

        push_reversed_words(d0,d1)

        /* this is precompiled to:

            push_reversed_words(d1)

            move.w  d0,-(a7)

           and this is further precompiled to:

            move.w  d1,-(a7)
            move.w  d0,-(a7)
        */

`#ifdef remainder' checks, whether the macro `remainder' is defined. If no
extra arguments are passed, `remainder' won't be defined, and the recursion
will stop then.

As you can see, you can define multi line macros by '{ ... }'. You can even
pass multi line arguments:

        #define loop(commands) {
        \LoopLable:
                commands
                bra     \LoopLable
        }

        loop ({
               sub.w    d0, d1
               beq      Exit
        })
        Exit:

        /* This is precomiled to:

            \LoopLable:
                    sub.w    d0, d1
                    beq      Exit
                    bra      \LoopLable
            Exit:
        */

But you should use the `#local' - directive, to do this in a better way.
(because if you use the macro many times, `\LoopLable' could appear many
times within the resulting asm - file, and this will certainly cause trouble)

Note, that macro contents aren't precompiled when the macro is read, but when
the macro is expanded. This is the difference to equates. Here a little
example:

        #define MyConstant 0
        #define LoadMyConstant  move.w #MyConstant, d0

        LoadMyConstant // is replaced by `move.w #0, d0'

        #undef MyConstant       // removes the macro `MyConstant'
        #define MyConstant 1    // redefine the macro `MyConstant'

        LoadMyConstant // is replaced by `move.w #1, d0'


Note, that you can't just redefine an existing macro by `#define Macro xxx'.
This will make PreFargo to output a warning. Use `#undef' to remove the
macro first.

Remember, that you can use '|' to separate macros or macro arguments from
words. You can use it for things like:

        #define push(arg_size, arg) move.|arg_size arg, -(a7)

        push (w, #$F000) // is extracted to `move.w #$F000, -(a7)'


  3.2.2.1 IMPORTANT
 -------------------

Parantheses within macro calls will be counted. Within inner parantheses
commas will be ignored.

#define PushEffectiveAddress (ea) {
        pea ea
}
        PushEffectiveAddress (0(a0,d0.w))

will be precompiled correctly. If you want to pass single parantheses to
macros, surround the hole argument by `{{'...`}}'.


Never forget, that there mustn't be whitespaces within a macro definition:
        #define  macro (x, y, z)   // completely wrong
        #define  macro(x,y,z)      // is ok

Equates or macros that are defined within another macro will be removed after
the macro is expanded. Macros may only redefine existing equates or macros.


  3.2.2 Equates
 ---------------

Equates are very similar to macros. But Equates may not contain arguments,
and they are precompiled on definition, not on expansion. PreFargo won't also
output an error, if an equate is redefined. That's why equates can be used
as counters etc.. Equates are defined by `#equ', and removed like macros by
`#undef'.

Here is the example from 3.2.1, but this time with Equates:

        #define MyConstant 0

        #equ LoadMyConstant  move.w #MyConstant, d0
          /* because it is an equate, it is directly precompiled to
             `move.w #0,d0'
          */

        LoadMyConstant // is replaced by `move.w #0, d0'

        #undef MyConstant       // removes the macro `MyConstant'
        #define MyConstant 1    // redefine the mycro `MyConstant'

        LoadMyConstant  /* is still replaced by `move.w #0, d0', in opposite
                           to the example from 3.2.1 */

Another example:

        /**
         * define the equivalent to the C-structure
         *    struct a {int a; long b; int c};
         */
        #equ    Offset 0
        #equ    a Offset
        #equ    Offset Offset+2   // `int a' takes 2 bytes
        #equ    b Offset
        #equ    Offset Offset+4   // `long b' takes 4 bytes
        #equ    c Offset
        #undef  Offset

        /** a0 points to such a structure */

        move.w  a(a0), d0       // load d0.w with structure->a (0(a0))
        move.l  b(a0), d1       // load d1.l with structure->b (0+2(a0))
        move.w  c(a0), d2       // load d2.w with structure->c (0+2+4(a0))


 ---------------------------------------
     3. 3. Include files
 ---------------------------------------

PreFargo can include files into the destination programm by the `#include'
directive. Files that are included in this way will also be preprocessed,
when they are inserted. There are two ways to specify a file to be included:

        1.  #include <incfile.h>
        2.  #include "incfile.h"

The two examples only differ in the path in which the file is searched.
`#include <...>' will search in the `%fargo%\asm\include' directory, or in
the directory, that is specified by the `/i<directory>' option of PreComp.exe.
(see PreFargo.bat)
`#include "..."' will search in `%fargo%\asm\prgm', or in the directory, that
was specified to PreComp by `/s<directory>'.

Be carefull, to don't nest #includes. You can check, whether an include-file
is allready present, by `#ifdef' and similar directives. See section 3.4. for
details.


 ---------------------------------------
     3. 4. Conditional Assembling
 ---------------------------------------

Conditional assembling is done by the keywords `#ifdef', `#ifndef', `#else',
`#endif'. These keywords can make PreFargo to include or don't include
passages from the source programm into the destination programm, when a macro
 is/isn't defined. `#error' can be used, to abort PreFargo with an error
 message.


  3.4.1 #ifdef
 --------------

Example:
        #ifdef Macro
           Commands
        #endif

This will insert `Commands' into the destination programm, if the macro
`Macro' is defined. Else it will skip everything until it reaches `#endif'.


  3.4.2 #ifndef
 ---------------

Example:
        #ifndef Macro
           Commands
        #endif

This is the opposite keyword to `#ifdef'. `Commands' will be inserted into
the destination, only if the macro `Macro' is _not_ defined. Else everything
till `#endif' is skipped.


  3.4.3 #else
 -------------


Example:
        #ifdef Macro
           Commands1
        #else
           Commands2
        #endif

`#else' can be used, to insert commands into the destination, if the above
`#ifdef'- or `#ifndef'-block is skipped. In the example `Commands1' will
be added to the programm, if `Macro' is defined, else `Commands2' is inserted.


  3.4.4 #endif
 --------------

Terminates a conditional block (see the above examples).


  3.4.5 #error
 --------------

`#error' is used to abort PreFargo with an error message.

Example:
        #ifndef Everything_Ok
          #error Something is wrong!
        #endif


Conditional assembling can also be used, to make sure, that an include file
isn't included twice, e.g.:

-----------------------------------------------------------------------------
/****************************************
 * Example.h
 **
 * defines the Fargo library routines example::Routine1 and
 * example::Routine2
 */

#ifndef EXAMPLE_H
        #define EXAMPLE_H

        /**
         * example::Routine1
         *-------------------
         * does nothing
         */
        #equ example::Routine1 example@0000

        /**
         * example::Routine2
         *-------------------
         * does the same as example::Routine1
         */
        #equ example::Routine2 example@0001
#endif
-----------------------------------------------------------------------------

In this example the include file is skipped, when the macro `EXAMPLE_H' is
allready defined. This macro is only defined, when the include-file has
allready been included.


 ---------------------------------------
     3. 5. Local Symbols
 ---------------------------------------

Local symbols are defined by `#local', and removed afterwards by `#endlocal'.

Example:

        #local LoopLabel
        MyFunction1:

        LoopLabel:
                ...
                bra LoopLabel
        #endlocal

In this example `LoopLabel' can only be accessed in the range from `#local'
to `#endlocal'. This is done, by replacing each occurence of `LoopLable'
by `LoopLable___XXXX', where `XXXX' is a number, that makes the symbol
`LoopLable' unequivocal. You can use `#local' to make sure, that labels
doesn't double within your programm. E.g.:

        MyFunction1:
        LoopLabel:
                  ...
                  bra LoopLabel
                  ...
                  rts

        MyFunction2:
        LoopLabel:
                  ...
                  bra   LoopLabel
                  ...
                  rts

In this example `LoopLable' exists twice. This will cause assembling errors.
To prevent this, you can use `#local LoopLabel':

        #local LoopLabel
        MyFunction1:
        LoopLabel:
                  ...
                  bra LoopLabel
                  ...
                  rts
        #endlocal

        #local LoopLabel
        MyFunction2:
        LoopLabel:
                  ...
                  bra   LoopLabel
                  ...
                  rts
        #endlocal


`#local' can also be nested. This is necessary, to use labels within macros:

        #define Loop(commands) {
               #local LoopLabel
        LoopLabel:
                 commands
                 bra LoopLabel
               #endlocal
        }

        Loop ({
             move.w d0, (a0)+
             subq.w #1, d0
             beq    Exit
        })
        Exit:

If you nest `#local', you will still be able to access symbols, that are
within the last `#local' - block. But if symbols are within the current
block, and in the last, the current symbol will have a higher priority:

        #local a,b,c
        a: ...       ;<-----------------------+
        c: ...       ;<--------------------+  |
        b: ...       ;<-----------------+  |  |
                     ;                  |  |  |
          #local a   ;                  |  |  |
        a:           ;<--------------+  |  |  |
             ...     ;               |  |  |  |
             bra  a  ; branch: >-----+  |  |  |
             bra  b  ; branch: >--------+  |  |
             bra  c  ; branch: >-----------+  |
                                              |
          #endlocal                           |
                                              |
          bra  a     ; branch: >--------------+

        #endlocal


  =======================================
      4. Suggestions
  =======================================

I didn't included something like a standard PreFargo include file, for the
reason that I didn't had enough time and not much experience with PreFargo
yet. This section includes some examples for macro constructions, that should
be very helpful. Create yourself an include file, from what you think is the
best. If you think, you created some very nice macros etc. send them to me,
I will then perhaps include them to future releases of PreFargo.


/**
 * pushr - Pushs values onto the stack in reversed order (e.g. for tios-
 *         routines)
 **
 * Example:
 *   pushr (#64,w, #10,w, #String,l, #4,w)
 *   jsr   tios::DrawStrXY
 *   lea   10(a7), a7
 */
#define pushr(value,v_size,remainder...) {
        #ifdef remainder
          pushr(remainder)
        #endif

        move.|v_size    value, -(a7)
}


/**
 * saveuregs - Saves all registers, that are marked to be used, by the macros
 *             d0_used, d1_used, ..., a6_used. If no register is used, the
 *             macro will expand to nothing.
 * resturegs - Restores all those registers
 **
 * Example:
 *   move.w Value(PC), d0
 *   #define d0_used
 *   lea    Value(PC), a0
 *   #define a0_used
 *
 *   saveuregs  // save all used registers (in this case: d0/a0)
 *   jsr      tios::ST_eraseHelp
 *   resturegs  // restore all used registers (in this case: d0/a0)
 */

#define saveuregs {
        #ifdef d0_used
          movem.l d0#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef d1_used
          movem.l d1#ifdef d0_used|/d0#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef d2_used
          movem.l d2#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef d3_used
          movem.l d3#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef d4_used
          movem.l d4#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef d5_used
          movem.l d5#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef d6_used
          movem.l d6#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef d7_used
          movem.l d7#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef a0_used
          movem.l a0#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef a1_used
          movem.l a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef a2_used
          movem.l a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef a3_used
          movem.l a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef a4_used
          movem.l a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef a4_used
          movem.l a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a6_used|/a6#endif, -(a7)
        #else #ifdef a5_used
          movem.l a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif, -(a7)
        #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif
}

#define resturegs {
        #ifdef d0_used
          movem.l (a7)+, d0#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef d1_used
          movem.l (a7)+, d1#ifdef d0_used|/d0#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef d2_used
          movem.l (a7)+, d2#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef d3_used
          movem.l (a7)+, d3#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef d4_used
          movem.l (a7)+, d4#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef d5_used
          movem.l (a7)+, d5#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef d6_used
          movem.l (a7)+, d6#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef d7_used
          movem.l (a7)+, d7#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef a0_used
          movem.l (a7)+, a0#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef a1_used
          movem.l (a7)+, a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef a2_used
          movem.l (a7)+, a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef a3_used
          movem.l (a7)+, a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef a4_used
          movem.l (a7)+, a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a5_used|/a5#endif#ifdef a6_used|/a6#endif
        #else #ifdef a4_used
          movem.l (a7)+, a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a6_used|/a6#endif
        #else #ifdef a5_used
          movem.l (a7)+, a1#ifdef d0_used|/d0#endif#ifdef d1_used|/d1#endif#ifdef d2_used|/d2#endif#ifdef d3_used|/d3#endif#ifdef d4_used|/d4#endif#ifdef d5_used|/d5#endif#ifdef d6_used|/d6#endif#ifdef d7_used|/d7#endif#ifdef a0_used|/a0#endif#ifdef a1_used|/a1#endif#ifdef a2_used|/a2#endif#ifdef a3_used|/a3#endif#ifdef a4_used|/a4#endif#ifdef a5_used|/a5#endif
        #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif
}


/**
 * near - Allows you to access any data within your programm a6 - relative.
 *        This will decrease the size of the Fargo relocalization table, and
 *        the size of the access-command (relative addresses are only 16bits)
 **
 * Example:
 *  lea __near_data(PC), a6     // a6 mustn't be modified from now on!!!
 *   ...
 *  move.w  #1234, near(var)
 *  move.b  '+', near(string)
 *   ...
 *  __near_data:
 *  var:    dc.w  0
 *  string: dc.w "-1234.5", 0
 */
#define near(labelname) labelname-__near_data(a6)

/***************************************************************************
 * Some macros, that should help you to structure your programm
 */

/**
 * loop - creates an endless loop, out of a given command-block
 * Example:
 *   loop ({
 *       subq.w #1, d0
 *       move.w d0, (a0)+
 *       beq    Exit
 *   })
 *   Exit:
 */
#define loop(commands) {
  #local @LoopLabel
@LoopLabel:
        commands
        bra     LoopLabel
  #endlocal
}

/**
 * for - creates a loop, that exits, when a word-counter reaches -1
 * Example:
 *   movea.l #LCD_MEM, a0
 *   move.w #959, d7
 *   for (d7, {
 *       clr.l (a0)+
 *   }
 */
#define for(reg,commands) {
  #local @LoopLabel
@LoopLabel:
        commands
        dbra     reg, LoopLabel
  #endlocal
}

/**
 * ifeq - creates an if-block, that is executed, when the last operation's
 *        result was zero, or equal(cmp).
 * Example:
 *   tst.w d0
 *   ifequ ({
 *     move.w   #-1, d0
 *   })
 */
#define ifequ(commands) {
  #local @SkipLabel
        bne   @SkipLabel
        commands
@SkipLabel:
  #endlocal
}

/**
 * Any other things, like ifne, ifgt, ifequ_else etc. - create them yourself.
 */

  =======================================
      5. End
  =======================================

This programm is freeware, I will send the sources to anyone who wants them.

Question, suggestion, bugs, comments? (E)Mail me!

Email:  dkuehlin@hell1og.be.schule.de (don't mix up '1' and 'l')
        (valid till june 2000)

Mail:   David Khling
        Lion-Feuchtwanger Str. 44
        12619 Berlin
        GERMANY


