The Guide to 68000 Assembly Language

From AtariForumWiki

Jump to: navigation, search

                66666     88888     00000     00000     00000
               6666666   8888888   0000000   0000000   0000000
              666   666 888   888 000   000 000   000 000   000
              666       888   888 000   000 000   000 000   000
              666       888   888 000   000 000   000 000   000
              66666666   8888888  000   000 000   000 000   000
              666666666 888   888 000   000 000   000 000   000
              666   666 888   888 000   000 000   000 000   000
              666   666 888   888 000   000 000   000 000   000
               6666666   8888888   0000000   0000000   0000000
                66666     88888     00000     00000     00000



                     THE GUIDE TO 68000 ASSEMBLY LANGUAGE

                            FOR FARGO PROGRAMMERS

                                 VERSION 1.1.1


                      by Jimmy Mardell <yarin@acc.umu.se>




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

                              0.0 ADMINISTRIVIA

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



                               ----------------
                                0.01  CONTENTS
                               ----------------

  0.00  ADMINISTRIVIA

  0.01  Contents
  0.02  Read this first!

  1.00  ABOUT MOTOROLA 68000

  1.01  Registers
  1.02  Flags
  1.04  Some information about the instructions
  1.05  Effective address
  1.06  The stack
  1.07  How to use the libraries
  1.08  How to address variables
  1.09  Handles
  1.10  Common errors

  2.00  INSTRUCTION SUMMARY

  2.01  How the summary is structured
  2.02  Data movement
  2.03  Integerarithmetic
  2.04  Logical operations
  2.05  Shift and rotation
  2.06  Bitmanipulation
  2.07  BCD-instructions
  2.08  Programcontrol
  2.09  Systemcontrol
  2.10  Other instructions

  3.00  PROGRAMMING STUFF

  3.01  The video memory
  3.02  Highscores etc
  3.03  Arrays

  4.00  MISCELLANEOUS

  4.01  Version history
  4.02  Greetings
  4.03  How to contact me


                           ----------------------
                            0.02 READ THIS FIRST!
                           -----------------------
 This guide can be used alone if you allready know some assembly programming.
In this case, this instruction set and fargo doc is enough.
 If you are new to assembly programming, it could be usefull to read the
guide: tutorial.zip available at ticalc.org. Please, note that a few sections
were removed from version 1.0 so that this guide is a better complement to
the tutorial.zip guide. All reference done to other files not belonging to
fargo distribution are reference to some files included in tutorial.zip.

This guide is NOT for newbies. It almost requires that you know something
(much something) about another assembly language (Z80, x86 etc). If you
just know a few high level languages (such as Pascal, Basic, C/C++) you
could of course learn from this guide (it isn't THAT cryptict) but I
recommend that you read some stuff about low level language programming.

I assume you know what binary, hexadecimal, two complement, register, flags,
stack are and all other basic things that you MUST KNOW when programming in a
lowlevel language.

If you think that anything important is missing, mail me!
See 4.03 How to contact me for more information.
And when contacting me, PLEASE tell me which version of this guide you have!!
If you got an old version and ask a question that have been fixed in the
current version, misunderstandings may arise.

Now over to the guide...



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

                           1.0 ABOUT MOTOROLA 68000

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



                               ---------------
                                1.01 REGISTERS
                               ---------------

The 68000 has 16 register, 8 data registers (D0-D7) and 8 address registers
(A0-A7) and they are all longword, ie 32 bit. No data or address register
is different from any other. That means whenever you can use D0, you can
always use D1-D7 also, the D0 register isn't a "main register", as the
A register is on a Z80, or the registers on a x86 where all registers are
made for different purposes (AX - accumulator, CX - counter, SI,DI - pointers
etc). The only real difference between the registers is data regs vs the
address regs.

One important thing is that if you have a longword stored in a data register
and you move a byte into it, the most significant three bytes are still there!
This may cause problems when you later add or multiplicate the register, you
MUST clear the most significant part!

The 68k also has a PC, Program Counter, as most CPU have. Works the
same way too (it is a 24 bit reg). The stack pointer is actually the A7
register, so maybe you should say that A7 works differently compared to A0-A6,
but it doesn't really. You could use A6 as stack pointer, except that all ROM
routines and the CPU itself ( see Bsr and Jsr ) use A7 as SP so it wouldn't be
a good idea...


                                 ------------
                                  1.02 FLAGS
                                 ------------

Then we have the flags. They're stored in the status register (SR), a 16 bit
register. It's divided into two parts, the systembyte (bit 15-8) and the
userbyte (or flagregister) (bit 7-0). 
Here's a description over the whole SR register:


 Bit 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
    -------------------------------------------------
    | T| -| S| -| -| I2,1,0 | -| -| -| X| N| Z| V| C|   - the status register
    -------------------------------------------------

* The Systembyte

Bit 15: T - The trace bit. If it's set an interrupts will be called after
        each instruction. Often used in debuggers.

Bit 13: S - Supervisor bit. When this bit is set, you have more "access" to
        some instructions and also to the systembyte. The reason for this is
        that it prevents programs to disturb the OS with some instructions
        that you shouldn't use if you're not writing an OS. Is enabled
        when interruptions are generated.

Bit 8-10: The interrupt mask

 The I0, I1 and I2 bits of the system register are used to set the interrupt
mask: in fact, it means that they are set to an interupt level: if the trap 
generated has a level higher than the interrupt mask, then the trap is
executed. Otherwise it is ignored. ( ignoring a trap generally means that
another interrupt, with a higher priority is beeing treated )

Here is how these bits are set:

        | I2 | I1 | I0 |

level 0 |  0    0    0 |  ---------> lowest priority
level 1 |  0    0    1 |
level 2 |  0    1    0 |
level 3 |  0    1    1 |
level 4 |  1    0    0 |
level 5 |  1    0    1 |
level 6 |  1    1    0 |
level 7 |  1    1    1 |  ---------> highest priority


Note: #0=%000; #1=%001; #2=%010; etc...
One should refer to the \system.txt file and \lesson\lesson_3.txt for more on
interruptions.


* The flagregister

- C-flag (Carry). Works as carry is used to work. If you add two 8 bit numbers,
  the C-flag will be the 9th bit. Also used with shift and rotation.

- V-flag (oVerflow). Will be set if a result can't be represented. For example,
  when you add $7F and $01, $80 can't be stored since that means -128 in
  two complement.

- Z-flag (Zero). Is set if the result of an operation is zero.

- N-flag (Negative). If the highest bit in the result is set (in two
  complement it means the sign bit), N will be set.

- X-flag (eXtended). This flag is a copy of the carry-flag, but it won't
  be changed in all operations where C is changed. This allows you to
  first make a check (that will set C and X), then some other instructions
  that will change the C flag but not the X flag, and THEN you can make
  the branch according to the flags, which means you can use the X flag.


                   ---------------------------------------
                    1.03 HOW DATA IS STORED IN THE MEMORY
                   ---------------------------------------

 The 68000-processor supports two different datatypes: binary and BCD
Float numbers are not supported. One needs a coprocessor. I don' t know
whether there exist one for the 68000 processor.
 Data is stored the "Big Indian" way: 
 The Z80 and x86 stores binary numbers with the LSB in the first byte, ie
$12345678 is stored $78,$56,$34,$12 in the memory. The 68k stores it the
other way around, $12,$34,$56,$78. That way to store numbers in the memory
is called "Big Indian".


                ----------------------------------------------
                 1.04 SOME INFORMATION ABOUT THE INSTRUCTIONS
                ----------------------------------------------

Most instructions on the 68k have a suffix that shows how much data
should be used in the instructions. This can be a byte (.B), a word
(.W) or a longword (.L). Another very important thing is that all
instructions are backwards (compared to most CPUs). With that I mean
that the source of the instruction is the first arg and the destination
is the last arg. For example: MOVE.W D0,D1 moves (actually, copies) the
first 16 bits (a word) from D0 to D1.


                           ------------------------
                            1.05 EFFECTIVE ADDRESS
                           ------------------------

The 68000s have 14 different ways to address things in the memory. This
example will use the instruction MOVE (LD on Z80, MOV on x86) to demonstrate
how they work. Later, in the instruction summary, you'll see that when an
instruction has <ea> (effective address) as an arg, it doesn't mean it can
use all 14 ways to address. It almost always has restrictions.


 1) IMMEDIATE ADDRESSING WITH DATA REGISTERS

    Syntax:  Dn (where n is 0-7)

    Example: MOVE.L D1,D0 copies the contents of D1 to D0. When the
             instruction is executed, both registers will contain the same
             information. When moving a byte or a word, the upper part of the
             register will remain unchanged.

         Instruction     Before        After
        --------------------------------------------
        |MOVE.B D1,D0  | D0=FFFFFFFF | D0=FFFFFF67 |
        |              | D1=01234567 | D1=01234567 |
        --------------------------------------------
        |MOVE.W D1,D0  | D0=FFFFFFFF | D0=FFFF4567 |
        |              | D1=01234567 | D1=01234567 |
        --------------------------------------------

 2) IMMEDIATE ADDRESSING WITH ADDRESSREGISTERS

    Syntax:  An (n is 0-7)

    Example: MOVE.L A1,D0 copies whole A1 to D0. After the instruction, both
             registers contain the same information. When transfering with
             addressregisters you must use word or longword. When a word is
             transfered TO an address register, bit 15 (the sign bit) will be
             copied trough the whole upper word (bit 16-31). If it wasn't so,
             a negative number would become positive.

         Instruction     Before        After
        --------------------------------------------
        |MOVE.W A1,D0  | D0=FFFFFFFF | D0=FFFF4567 |
        |              | A1=01234567 | A1=01234567 |
        --------------------------------------------
        |MOVE.W D0,A1  | D0=01234567 | D0=01234567 |
        |              | A1=FFFFFFFF | A1=00004567 |
        --------------------------------------------
        |MOVE.W D0,A1  | D0=0000FFFF | D0=0000FFFF |
        |              | A1=00000000 | A1=FFFFFFFF |
        --------------------------------------------

 3) INDIRECT ADDRESSING WITH ADDRESSREGISTERS

    Syntax:  (An) (n is 0-7)

    Example: MOVE.L (A0),D0 copies the longword stored at address location
             A0 (you say A0 points to the longword). If you refer to a word
             or a longword, the address in the address register must be an
             even number. THIS CAN CAUSE BIG PROBLEMS AND UNEXCEPTED ERRORS!!

         Instruction      Before           After
        ---------------------------------------------------
        |MOVE.L (A1),D0 |    D0=FFFFFFFF |    D0=01234567 |
        |               |    A1=00001000 |    A1=00001000 |
        |               | $1000=01234567 | $1000=01234567 |
        ---------------------------------------------------

 4) INDIRECT ADDRESSING WITH ADDRESSREGISTERS WITH AFTERINCREASMENT

    Syntax:  (An)+ (n is 0-7)

    Desc.:   Works as the previous addressing mode, except that after the
             instruction, An will be increased with the size of the operation.
             A special case is when you use A7 and transfer a byte, because A7
             will be increased with 2 instead of 1, because A7, as stack
             pointer, must be an even number.

    Example: MOVE.L (A1)+,D0 copies the longword which A1 points to to D0,
             and increases A1 with 4.

         Instruction       Before           After
       ----------------------------------------------------
       |MOVE.L (A1)+,D0 |    D0=FFFFFFFF |    D0=01234567 |
       |                |    A1=00001000 |    A1=00001004 |
       |                | $1000=01234567 | $1000=01234567 |
       ----------------------------------------------------

 5) INDIRECT ADDRESSING WITH ADDRESSREGISTERS WITH PREDECREAMENT

    Syntax:  -(An) (n is 0-7)

    Desc.:   Works as the previous addressing mode, except that An will first
             be decreased with the operand size (with the exception of A7),
             then the data will be transfered.
    Example: MOVE.L -(A1),D0 first decreases A1 with 4, then copies the
             longword stored at A1 to D0.

         Instruction       Before           After
       ----------------------------------------------------
       |MOVE.L (A1)+,D0 |    D0=FFFFFFFF |    D0=01234567 |
       |                |    A1=00001004 |    A1=00001000 |
       |                | $1000=01234567 | $1000=01234567 |
       ----------------------------------------------------

 6) INDIRECT ADDRESSING WITH ADDRESSREGISTER WITH SHIFTING

    Syntax:  x(An) (x is 16 bit, n is 0-7)

    Desc.:   The location pointed at x+An is the one that will be copied.

    Example: MOVE.L 4(A1),D0 copies the longword stored at A1+4 to D0. A1
             will, after the instruction, remain unchanged. Note that if x
             is bigger than $7FFF, it means a negative value. It's because of
             the sign extension.

        Instruction       Before           After
       ----------------------------------------------------
       |MOVE.L 4(A1),D0 |    D0=FFFFFFFF |    D0=01234567 |
       |                |    A1=00001000 |    A1=00001000 |
       |                | $1004=01234567 | $1004=01234567 |
       ----------------------------------------------------

 7) INDIRECT ADDRESSING WITH ADDRESSREGISTER WITH SHIFTING

    Syntax:  x(An,Dn.L) (x is 8 bit, n is 0-7)
             x(An,Dn.W)
             x(An,An.W)
             x(An,An.L)

    Desc.:   Works as the previous addressing mode, except that another
             register also will be added (if it's a word, a sign extension
             will be made before, so it will be a subtraction). When working
             with words or longwords, the generated address must be an even
             address.

    Example: MOVE.L 4(A1,A2.L),D0 copies the longword stored at A1+A2+4 to D0.
             A1 and A2 will after the instruction remain unchanged. Note that
             if x is bigger than $7F, it means a negative value. It's because
             of the sign extension.

        Instruction            Before           After
       ---------------------------------------------------------
       |MOVE.L 4(A1,A2.L),D0 |    D0=FFFFFFFF |    D0=01234567 |
       |                     |    A1=00001000 |    A1=00001000 |
       |                     |    A2=00001000 |    A2=00001000 |
       |                     | $2004=01234567 | $2004=01234567 |
       ---------------------------------------------------------

 8) ABSOLUTE ADDRESSING (NEAR)

    Syntax:  x (x is a 16 bits constant)

    Desc.:   The address will be sign extensioned before it's used, but the
             MSB is ignored (don't bother about that). The sign extension
             means that near addressing can only be used on the first 32Kb.

    Example: MOVE.L $1000,D0 copies the longword stored at $1000 to D0. Note
             that there is no parentheses! If you mean an immediate value,
             you put a # before the value (see below). However, adding the
             parentheses is not a bad idea: the assembler will accept it and
             it will add in readability to the source.

        Instruction       Before           After
       ----------------------------------------------------
       |MOVE.L $1000,D0 |    D0=FFFFFFFF |    D0=01234567 |
       |                | $1000=01234567 | $1000=01234567 |
       ----------------------------------------------------

 9) ABSOLUTE ADDRESSING (FAR)

    Syntax:  x (x is a 32 bits constant)

    Desc.:   Works EXACTLY as the above move, except that x is a 32 bits
             value (the instruction is two bytes longer also).

    Example: MOVE.L $10000,D0 copies the longword stored at $10000 to D0.

        Instruction        Before            After
       -------------------------------------------------------
       |MOVE.L $10000,D0 |     D0=FFFFFFFF |     D0=01234567 |
       |                 | $10000=01234567 | $10000=01234567 |
       -------------------------------------------------------

10) PROGRAMCOUNTER WITH SHIFTING

    Syntax:  x(PC) (x is a 16 bits constant)

    Desc.:   The word (x) that follows the instruction will be added to
             the programcounter to get the memory location. The word will
             be sign extensioned before (meaning that the limits are
             -32768 to +32767). The value used for the programcounter is the
             address to x, not to the instruction (don't bother).

    Example: MOVE.L $100(PC),D0 copies the longword stored at PC+$102 (102
             because the value $100 is stored 2 bytes after the instruction)
             to D0.

       Instruction          Before           After
      -------------------------------------------------------
      |MOVE.L $100(PC),D0 |    D0=FFFFFFFF |    D0=01234567 |
      |(assuming PC=$1000)| $1102=01234567 | $1102=01234567 |
      -------------------------------------------------------

11) PROGRAMCOUNTER WITH INDEX

    Syntax:  x(PC,Dn.L) (x is 8 bits, n is 0-7)
             x(PC,Dn.W)
             x(PC,An.W)
             x(PC,An.L)

    Desc.:   Works as the previous one except that a dataregister or an
             an address register is added (with sign extension). Similiar
             to addressing mode 7.

    Example: MOVE.L $10(PC,A1.L),D0 copies the longword stored at PC+A1+$12
             to D0.

       Instruction              Before           After
      -----------------------------------------------------------
      |MOVE.L $10(PC,A1.L),D0 |    D0=FFFFFFFF |    D0=01234567 |
      |(assuming PC=$1000)    | $2102=01234567 | $2102=01234567 |
      |                       |    A1=00001000 |    A1=00001000 |
      -----------------------------------------------------------

12) IMMEDIATE ADDRESSING

    Syntax:  #x (x is 8, 16 or 32 bits)

    Desc.:   Uses the immediate value x.

    Example: MOVE.L #$10002000,D0 copies $10002000 to D0. Note that if you
             copy a word to an addressregister, the word will be sign
             extensioned.

       Instruction            Before        After
      ---------------------------------------------------
      |MOVE.L #$10002000,D0 | D0=01234567 | D0=10002000 |
      |                     |             |             |
      ---------------------------------------------------

13-14) ADDRESSING WITH THE STATUSREGISTER

    Syntax:  SR
             CCR

    Desc.:   The only instructions that are allowed to use this addressing
             mode are: ANDI (AND immediate), EORI (exclusive OR immediate) and
             ORI (OR immediate). If the length is a byte, the flag register is
             changed. If it's a word, both the flag register and the
             systembyte are changed (but then the supervisor bit, 13, must be
             set).
             The assembler recognize both SR (that means both flags and
             system-byte) and CCR (only flag register), so you don't have to
             specify the length.

    Example: The instruction ORI #5,CCR sets both the carryflag (C) and the
             zeroflag (Z). The other flags remains unchanged.
             Note: #5=#%00000101

       Instruction   Before     After
      ------------------------------------
      |ORI #5,CCR  | CCR=0000 | CCR=0005 |
      ------------------------------------


                               ----------------
                                1.06 THE STACK
                               ----------------

As mentioned earlier, A7 works as stack pointer. The stack ( user and system
stack ) is stored in the "system memory":  you should not bother about the
size: it should allways be more than enough...
You may have noted one thing if you jumped to the instruction summary
at once: there are no push/pop instructions! That's because they're
not necessary, MOVE will do the job for us.

For example, if we want to push D0.W (with this I mean D0, the lower
16 bits) we just MOVE.W D0,-(A7). And to pop it back, just MOVE.W (A7)+,D0.
Remember that when popping a word, the upper 16 bits in D0 is still there.

When you want to push many registers at once, for example in the beginning
of a subroutine, it may be a bit boring to type all the move instruction
(and it will take a lot of bytes also). There is a shortcut: MOVEM. With
this instruction you can push (or just copy) many registers at once.
If you want to push D0-D4 and A0-A2 for example, you just

 movem d0-d4/a0-a2,-(a7)

and then

 movem (a7)+,d0-d4/a0-a2

Very handy...

Another way to put things on the stack is with the PEA instruction. It
pushes an effective address on the stack, used when pushing pointers. This
will decrease A7 with 4 (the size of a pointer).


                       -------------------------------
                        1.07 HOW TO USE THE LIBRARIES
                       -------------------------------

In most libraries, you just store the in paramters in some registers (read
the .h file for each library), then call it with jsr library_name::lib_label,
for example: jsr flib::idle_loop. That library call hasn' t  any in
parameters, but when you've pressed a key (idle_loop waits until a key is
pressed), D0 will contain the character code of the key pressed. Before using
a library function, you should check out the parameters, since it's not
good if some important registers get destroyed in a library. Some libraries
will push all registers that will be changed and pop them back at the end,
with the exception of the out paramters of course. Most of the tios routines
will destroy some registers.

                       --------------------------------
                        1.08  How to address variables
                       --------------------------------

How do we address things? How do I copy the word stored at var1 to D0?
It's very simple, just

 move.w  (var1),d0

Note, ( ) is not needed. And, as usual, the upper 16 bits are unaffected.

And, how to make A0 point at str1? Also easy,

 lea     str1(PC),a0

You MUST type (PC) after the label, else it won't work! This is just a way
to address a label (see 1.05 Effective Address)

After loading A0 with the pointer to str1, you can get the first byte with

 move.b  (a0)+,d0

This copies the first byte ('H' = 72) to D0 and increases A0 with one, thus
pointing to the next character. Now you must use parantheses since else
it would mean copy A0, not the byte stored at A0, to D0.


                               ---------------
                                1.9  Handles
                               ---------------

You should read HANDLES.TXT that comes with Fargo to find out what they
are, but here is how to use them. If you want to create a big array, for
example a map or something else that is more than 10-20 bytes, you should
create a handle to make your program shorter, since all temporary variables
are stored inside the program.

Lets say we want to create a table of 128 words. Then we should use the
following code:

 move.l  #$0100,-(a7)              ; 128 words = 256 byte = $0100 bytes
 jsr     tios::HeapAlloc           ; Call the rom function
 add.l   #$04,a7                   ; Restore the stack pointer
 move.w  d0,table_handle           ; Store the handle number in a var
 tios::DEREF d0,a0                 ; Get the address to the handle
 move.l  a0,table_addr             ; And store the address in another var

 .
 .
 .

 table_handle  dc.w 0              ; Here is the handle number for the table
 table_addr    dc.l 0              ; And here is that address


As you see, you should push the size onto the stack, and you must push it
as a longword, else it won't work. The routine will return the handle
number in D0.W, which you MUST store in a variable, because you'll need
it when you later must destroy the handle.

Now, when you got the handle number, you also need to know WHERE in the
RAM the handle is, ie at which address. To get this address, you should
use a macro in tios.h (needs to be included) called tios::DEREF. It's a
simple macro, it just looks up a table in the system memory (better explained
 in HANDLES.TXT or \system.txt, section IV.1).

Anyway, the macro has two parameters, the first is the given handle number
and the second is which address register the address should be returned
into. The address is, of course, an even number so we can address it
with (An). The address should also be saved in a variable. You could of
course use the macro whenever you want the address, but although it's
a simple macro (3 rows) it's a bit slower and takes some more bytes, so
it's better to define a longword and store the address there, because the
address won't change during the program execution.

Before you exit the program, you MUST destroy all created handles. I don't
know what will happen if you don't, memory corruption and calculator crashes
at least. Here is how to do that:

 move.w  table_handle(PC),-(a7)
 jsr     tios::HeapFree
 lea     2(a7),a7

When creating handles, you should also check if the operation succeded.
It won't succed if you're out of handles (don't worry about that...) or
if you're out of memory (this you MUST check, else CRASH)! For example,
when you're working with grayscale graphics, you need almost 4k free! If
the user don't know that, he/she won't be happy.

The HeapAlloc routine will return D0.L=0 if the operation didn't
succed, so it's easy to check. Then you should exit the program without
trying to destroy the handle (since you didn't get any handle number).


                           -----------------------
                            1.10  Common mistakes
                           -----------------------

"If anything can go wrong, it will. If it can't, it will anyway."

You get some strange errors messages at the top of the screen when running
your program? Calculator crashes? And you don't know what's wrong? Cool down,
that's very common :-)

But finding the errors in the source can be hard, VERY hard, sometimes. There
are some common mistakes though if you've programmed other assembly languages
(like me) before. Those are

 * You MUST put a # before an immediate value!! There are exceptions, for
   example LEA 10(A7),A7, but when using MOVE, CMP and other instructions
   it can be a fatal error. For example, MOVE.B $10,D0 means move the byte
   stored at address $10 to D0! This can cause protected memory error or
   something like that. Always check so you've not missed any #!

 * The first operand is the source, the second the destination! This is also
   a very usual error in the beginning. We should not speak of what it could
   do, but instead of getting things from imporant places in the RAM (like,
   the interrupt vector), you store some trash there! Nooot good! Check all
   instructions with two operands! Most instructions have two operands.

 * Since the upper part of the register will remain there until you move
   another longword to the register, it may cause big problems! For example,
   when getting a byte from somewhere in the memory, and then you want to
   multiplicate it, you MUST be sure that the upper part of the byte is
   cleared out, since you don't specify any operation size (.B, .W or .L)
   when multiplicating. To do this, use either CLR or EXT (see 2.0
   Instruction summary).

 * All tables and other variables you'll address with (An) must be at an
   even address. If you have defined one byte before the table, it will
   cause the table to start at an odd address, which will probably cause
   in a calculator crash. To avoid this, move all such tables/arrays at
   the beginning of the variable section (I think, or at least it seems so,
   all instructions have the size 2, 4, 6...). You may also use the "even"
   assembly directive which allign the table on a longword boundary.

 * Be sure you've destroyed all handles when exiting.

If you still don't find the error, you should use db92 to pinpoint 
the error. Be aware that when programming an assembly language, most of
the time (>50%) you're sitting and correcting bugs...


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

                           2.0 INSTRUCTION SUMMARY

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



                     ------------------------------------
                      2.01 How the summary is structured
                     ------------------------------------

The instructions are divided into 8 classes depending on how they work and
what they do. Here is a short description of all instructions the Motorola
68000 will understand:

DATA MOVEMENT
-------------
These instructions moves data from one place to another.

EXG   (EXchanGe) The contents of two registers will be exchanged.
LEA   (Load Effective Address) Calculates a memory location and store it in
      an address register.
LINK  Allocates a stackframe.
MOVE  Copies the contents in one register/memory location to another register
      or another memory location.
MOVEA (MOVE Address) Same as MOVE except that the destination is an address-
      register.
MOVEM (MOVE Multiple) transfers many registers to or from the memory.
MOVEP (MOVE Peripheral) transfers data to or from an 8 bits peripheralunit.
MOVEQ (MOVE Quick) puts a constant in a dataregister.
PEA   (Push Effective Address) calculates a memory address and stores it on
      the stack.
SWAP  Swaps the word in a dataregister.
UNLK  (UNLinK) removes a stackframe

INTEGERARITHMETIC
-----------------
These instructions perform simple twocomplement operations on binary data.

ADD, ADDA, ADDI, ADDQ, ADDX  Different kinds of addition.
CLR   Clears an operand.
CMP, CMPA, CMPI, CMPM  Compares two operands
DVIS, DIVU  Integer division, signed and unsigned.
EXT   Makes a sign extension, byte to word or word to longword
MULS, MULU  Multiplication, signed and unsigned.
NEG, NEGX  Twocomplements a number.
SUB, SUBA, SUBI, SUBQ, SUBQ  Different kinds of subtraction.
TAS   (Test And Set) used to synchronise more than one processor
TST   Compares an operand with 0.

LOGICAL OPERATIONS
------------------
These operations perform logical operations on binary numbers. A logical
operation is either "true" (1) or "false" (0).

AND, ANDI  Logical AND on two binary integers
OR, ORI    Logical OR
EOR, EORI  Exclusive OR (XOR)
NOT        Returns the operans onecomplement (0 -> 1, 1 -> 0)

SHIFT AND ROTATION
------------------
These instructions perform arithmetical and logical shift and rotation
with or without extra carry.

ASL, ASR   Arithmetic shift left resp right.
LSL, LSR   Locigal shift left resp right.
ROL, ROR   Rotation left resp right without extra carry.
ROXL, ROXR Rotation left resp right through extra carry.

BITMANIPULATION
---------------
These instructions affect single bits in a byte. All instructions test
the bit before affecting it.

BTST  Tests a bit
BSET  Tests a bit, then set it (1)
BCLR  Tests a bit, then reset it (0)
BCHG  Tests a bit, then invert it (0 -> 1, 1 -> 0)

BCD-INSTRUCTIONS
----------------
These operations work with BCD-numbers.

ABCD  BCD addition
SBCD  BCD subtraction
NBCD  BCD negate

PROGRAMCONTROL
--------------
These instructions contain branches, jumps, calls.

Bcc   A group of 15 instruction that branches depending on the flags.
DBcc  15 instructions that perform loops.
Scc   16 instructions that will set/reset a byte depending on the flags.
BSR, JSR  Subroutine calls.
RTS   Return from a subroutine.
JMP   Absolute jumps.
RTR   Pops the PC and the flags from the stacks.

SYSTEMCONTROL
-------------
These instructions changes the state of the 68000 processor. They require
that the supervisor bit (in the system byte) is set. I haven't used these,
so don't blame me if I've written something wrong.

MOVE USP    Gives a program in supervisor mode access to the stackpointer in
            user mode
RESET       Restores the peripheral units.
RTE         Returns from an interrupt.
STOP        Stops the execution until a given interrupt occurs.
CHK, TRAPV  Finds fatal program errors.
TRAP        16 instructions that give a program in usermode the possibility
            to call antoher program in supervisor mode.

OTHER INSTRUCTIONS
------------------
ILLEGAL     Causes an interrupt (Illegal instruction)
NOP         Does nothing :-) (No OPeration)


All instructions are divided into 5 parts: a description, addressmethods,
datalength, flags and syntax.

The addressmethods shows which operands are allowed. Often you can't combine
different addressmethods with each other, but that is explained in the
description.

In datalength you can see if you can use longwords, words or maybe only
a byte. Some instructions can use words if you choose one addressmethod,
but you can use byte or longword if you choose another addressmethod.

The flags part shows how the flags are set after the instruction has
been executed. It can either be one of the following symbols

S     - Standard setting - see below
0     - The flag is always cleared
1     - The flag is always set
undef - undefined, you can't be sure how the flag will be set
U     - unaffected, the flag hasn't changed during the instruction.

or a longer description, if it's a bit special.

The Z, N and V flags are often set the same way (standard setting). The Z flag
is usually set if the destination register (or the result) is zero, else the
flag is cleared. The N flag is usually set if the most significant bit of the
result is set (the most significant bit is the sign bit and shows if the
number is negative or positive). The V flag is often set if the instruction
resulted in an overflow (there weren't enough bits to store the answer in).

Many instructions don't change any flags, then you'll see "Unaffected"
directly after FLAGS.

The syntax shows how the instructions can look like. Often, letters (x
and y) is shown where there should be numbers between 0-7.

                     ------------------------------------
                      2.02  Data movement
                     ------------------------------------

*** EXG ***

Lets two data- or addressregister swap contents with each other. You can
swap a dataregister with an addressregister.

ADDRESSMETHODS: Dn, An

DATALENGTH: Longword

FLAGS:  Unaffected

SYNTAX: EXG Rx,Ry


*** LEA ***

Loads an effetive address into an addressregister. LEA is often used when
writing code that must be independent of the position in the memory (which
all Fargo programs are). It's often used with the addressmethods x(PC) or
x(PC,xr.s).
LEA also adds a constant to an addressregister without changing the flags,
and/or also an index with x(An,xr.s).

ADDRESSMETHODS: (An), x(An), x(An,xr.s), x.w, x.l, x(PC), x(PC,xr.s)

DATALENGTH: Longword

FLAGS:  Unaffected

SYNTAX: LEA <ea>,An


*** LINK ***

The instruction LINK creates a stackframe, a temporary allocated memory
on the stack. The instruction is often used in highlevel languages
when allocating memory for local variables in procedurs. When the procedure
is desactivated, the variables disappear which saves memory.
 LINK has two operands. The first is an addressregister and the second is
a twocomplement value, which is the size of the frame (often negative since
the stack grows backwards). When the instruction is executed, the address-
register is pushed onto the stack and the newly updated A7 is copied to
the addressregister. The immediate value is added to the Stack register ( A7).

 The local memory is accessed with negative shifting from the addressregister.
That way you can use local variables without bothering about other data
that is pushed or popped from the stack provided you keep in the range you
specified while calling the LINK opcode.
 The instruction UNLK removes the stackframe and restores the stackpointer.

ADDRESSMETHODS: None

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: LINK An,#<shifting>

Note that the use of LINK allows Reentrant programs.

*** MOVE ***

The instruction MOVE copies a byte, a word or a longword from an effective
address to another. The flags are set according to the data moved.

ADDRESSMETHODS (for the source): Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s),
                x.w, x.l, x(PC), x(PC,xr.s), #x

ADDRESSMETHODS (for the dest.>: Dn, (An), (An)+, -(An), x(An), x(An,xr.s),
                x.w, x.l

The addressmethod An can only be used when the datalength is word or longword.

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: MOVE <ea>,<ea>

The instruction MOVEA moves data to an addressregister (An is as you may have
noticed missing in addressmethods for the destination). Most assemblers choose
MOVEA is you have an addressregister as an operand.


*** MOVE to CCR ***

If you specify CCR as the destination, the lower byte in a word is copied
to the flagregister (CCR). The flags doesn't change according to the result,
ie if you clear the flagregister the Z flag won't be set.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, x(PC),
                x(PC,xr.s), #x

DATALENGTH: Word

FLAGS:  Set according to the bits of the byte you moved to CCR.

SYNTAX: MOVE <ea>,CCR


*** MOVE to SR ***

If you specify SR as the destination, a word is moved to the statusregister
(ie the systembyte and the flagbyte). The instruction requires that bit
13 (the supervisor bit) is set in the beginning of the instructions.
The instruction can be used to change the T-bit (trace), S-bit (supervisor),
the interruptmask and the flags. Note that with fargo II, to get in supervisor
mode, you should use the trap #1 .

If you only want to change the flags, you should use MOVE to CCR instead,
which also works if you are in user mode.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, x(PC),
                x(PC,xr.s), #x

DATALENGTH: Word

FLAGS:  Set according to the lower bits in the word you moved to SR.

SYNTAX: MOVE <ea>,SR


*** MOVE from SR ***

This instruction copies the whole statusregister to an operand with the
size of a word. It requires that you are in supervisor mode (the S-bit in
SR must be set).

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Word

FLAGS:  Unaffected

SYNTAX: MOVE SR,<ea>


*** MOVEA ***

The instruction MOVEA copies an operand given by an effective address to an
addressregister. Only words and longwords are used, and all 32 bits in the
destination are affected (sign extension if word).

ADDRESSMETHODS: Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                x(PC), x(PC,xr.s), #x

DATALENGTH: Longword

FLAGS:  Unaffected

SYNTAX: MOVEA <ea>,An

Most assemblers choose MOVEA if you use MOVE with an addressregister as
destination


*** MOVEM ***

The instruction MOVEM (MOVE Multiple) makes it possible to fast transfer
a group of registers to or from the memory. The operation can only work with
word or longword. When you move words to register, the words are signextended
so all 32 bits are affected.
 The instruction is most often used to push registers on the stack, so you
can temporary use those register to other things and later restore the
original values. Very useful in the beginning and the end of subroutines that
change a lot of registers.

ADDRESSMETHODS: (An), -(An), x(An), x(An,xr.s), x.w, x.l
(register to memory)

ADDRESSMETHODS: (An), (An)+, x(An), x(An,xr.s), x.w, x.l, x(PC), x(PC,xr.s)
(memory to register)

DATALENGTH: Word, longword

FLAGS:  Unaffected

SYNTAX: MOVEM <registerlist>,<ea>
        MOVEM <ea>,<registerlist>

The registerlist is a serie of registers separated by a slash ("/"). You can
also use one or many intervalls (shown with a "-"). For example, D0-D5/A0-A2
means the registers D0, D1, D2, D3, D4, D5, A0, A1, A2.


*** MOVEP ***

The instruction MOVEP (MOVE Peripheral) transfers a word or a longword in
a dataregister to or from every second memoryaddress. The MSB in the
dataregister transfers to or from the address x(An), - the only addressmethod -
the next byte to or from x+2(An) and so on. If the first address was odd all
MOVEP transfers will use the lowest byte in the 68000:s databus. Even addresses
use the highest byte.
 This instruction is mainly used when you use 8 bits databuses connected with
the 16 bits databus in the 68k. Since this is never done on the TI-92 (am I
right here??) this instruction won't be used that way.

ADDRESSMETHODS: x(An)

DATALENGTH: Word, longword

FLAGS:  Unaffected

SYNTAX: MOVEP Dn,x(An)
        MOVEP x(An),Dn


*** MOVEQ ***

The instruction MOVEQ (MOVE Quick) is used to put small immediate data in
a dataregister. The instruction is two bytes long and can handle constanst
in the range -128 and +127 (decimal). All 32 bits in the register are affected
If you used MOVE.L the instruction would take 6 bytes.

DATALENGTH: Longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: MOVEQ #<data>,Dn

Many assemblers automatically change a MOVE to a MOVEQ if possible.


*** PEA ***

The instruction PEA calculates an effective address and pushes it on the
stack. The address is always a longword.

ADDRESSMETHODS: (An), x(An), x(An,xr.s), x.w, x.l, x(PC), x(PC,xr.s)

DATALENGTH: Longword

FLAGS:  Unaffected

SYNTAX: PEA <ea>


*** SWAP ***


The instruction SWAP swaps the upper word with the lower word in a
dataregister (bit 31-16 is exchanged with bit 15-0).

ADDRESSMETHODS: Dn

DATALENGTH: Word

FLAGS:  X - U
        N - Same as bit 31 in the dataregister
        Z - Set if all 32 bits are zero, else cleared
        C - 0
        V - 0

SYNTAX: SWAP Dn


*** UNLK ***

The instruction UNLK (UNLinK) removes a stackframe that earlier was set by
the instruction LINK (see LINK). It works like this:
The given addressregister (usually the framepointer... :) ) is stored in the
stackpointer. Then the original state of the frame pointer is restored by
getting the first longword on the stack. This is the opposite of what LINK
does.
UNLK works correctly no matter what has been pushed or popped on the stack
between the instructions LINK and UNLNK but it requires that you popped your
variables from the frame pointer or updated the frame pointer to its initial
value ( by adding the size of the variables to the frame pointer for exemple ) 

ADDRESSMETHODS: -

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: UNLK An


                     ------------------------------------
                      2.03  Integerarithmetic
                     ------------------------------------

*** ADD ***

Adds two binary operands and stores the result in the destination operand.

Two different methods allowed:

1. Add an effective address to a dataregister.
2. Add a dataregister to an effective address.

ADDRESSMETHODS: 1) Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                   x(PC), x(PC,xr.s), #x

ADDRESSMETHODS: 2) (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

When using an addressregister as destination, byte is not allowed.

FLAGS:  X - Set if carry from the most significant bit, else cleared.
        N - S
        Z - S
        C - Same as X
        V - S

SYNTAX: ADD Dn,<ea>
        ADD <ea>,Dn


*** ADDA ***

Binary addition to an addressregister. To make it possible to mix
addressoperations with dataoperations, this instruction won't affect any
flags.

ADDRESSMETHODS: Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                x(PC), x(PC,xr.s), #x

The effective address must be the source.

DATALENGTH: Word, longword

ADDA affects always all 32 bits in the destination addressregister.

FLAGS:  Unaffected

SYTNAX: ADDA <ea>,An


*** ADDI ***

Adds a constant to an effective address. The source operand must be immediate.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - Set if carry from the most significant bit, else cleared.
        N - S
        Z - S
        C - Same as X
        V - S

SYNTAX: ADDI #x,<ea>

Most assemblers automatically choose ADDI if the source operand to an ADD
instruction is immediate.


*** ADDQ ***

This instruction adds a three bit immediate value to an effective address.
The instruction is very quick and much shorter than the usual ADD.

ADDRESSMETHODS: Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

When using an addressregister as destination, byte is not allowed.

FLAGS:  X - Set if carry from the most significant bit, else cleared.
        N - S
        Z - S
        C - Same as X
        V - S

No flags are affected if the destination operand is an addressregister.

SYNTAX: ADDQ #<data>,<ea>

#<data> is a constant between 1 and 8.


*** ADDX ***

The instruction ADDX (ADD eXtended) works as ADD but the X flag is also
added. This makes it possible to add big numbers stored in many bytes.

The instruction has two methods:

1. Add a dataregister to a dataregister.
2. Add a memory location to another memory location. You must use -(An) on
   both operands then.

ADDRESSMETHODS: Dn, -(An)

DATALENGTH: Byte, word, longword

FLAGS:  X - Set if carry from the most significant bit, else cleared.
        N - S
        Z - S
        C - Same as X
        V - S

The Z flags works in another way now, making it possible to check if a
big number (much bigger than 32 bits) is zero. You must set the zero flag
before making the addition though, shorter than comparing a register with
itself.

SYNTAX: ADDX Dy,Dx
        ADDX -(Ay),-(Ax)


*** CLR ***

This instruction (CLeaR) clears an operand specified with an effective
address.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - 0
        Z - 1
        C - 0
        V - 0

SYTNAX: CLR <ea>


*** CMP ***

CMP (CoMPare) compares a dataregister with an effective address. The flags
are affected the same way as if the effective address was substracted from the
dataregister. None of the operands are changed. Often used with the Bcc
instruction. An example:

 CMP  D0,D1
 BGT  X1

The program will branch to X1 if D1 is greater than D0, else the program will
continue.

ADDRESSMETHODS: Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                x(PC), x(PC,xr.s), #x

DATALENGTH: Byte, word, longword

Byte can't be used when comparing to an addressregister.

FLAGS:  X - U
        N - S
        Z - S
        C - Set if a borrow was needed when subtracting, else cleared
        V - S

SYNTAX: CMP <ea>,Dn

There are four CMP instructions, CMP, CMPA, CMPI and CMPM. The compiler
often choose the right instruction, so you can write CMP all the time if
you want.


*** CMPA ***

CMPA (CoMPare Address) compares an addressregister with an effective address.
The flags are affected the same way as if the effective address was subtracted
from the dataregister. None of the operands are changed. Often used with the
Bcc instruction. An example:

 CMP  A0,A1
 BGT  X1

The program will branch to X1 if A1 is greater than A0, else the program will
continue.

ADDRESSMETHODS: Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                x(PC), x(PC,xr.s), #x

DATALENGTH: Word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - Set if a borrow was needed when substracting, else cleared
        V - S

SYNTAX: CMPA <ea>,An

There are four CMP instructions, CMP, CMPA, CMPI and CMPM. The compiler
often chooses the right instruction, so you can write CMP all the time if
you want.


*** CMPI ***

CMPI (CoMPare Immediate) compares an immediate value with an effective address
The flags are affected the same way as if the effective address was
substracted from the dataregister. None of the operands are changed. Often
used with the Bcc instruction. An example:

 CMP  #<data>,D0
 BGT  X1

The program will branch to X1 if D0 is greater than the immediate value.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - Set if a borrow was needed when subtracting, else cleared
        V - S

SYNTAX: CMPI <ea>,Dn

There are four CMP instructions, CMP, CMPA, CMPI and CMPM. The compiler
often chooses the right instruction, so you can write CMP all the time if
you want.


*** CMPM ***

CMPM (CoMPare Memory) compares two memory locations with each other with
after-increament. The flags are affected the same way as if the source
was subtracted from the destination. None of the operands are changed.

ADDRESSMETHODS: (An)+

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - Set if a borrow was needed when subtracting, else cleared
        V - S

SYNTAX: CMPM (Ay)+,(Ax)+

There are four CMP instructions, CMP, CMPA, CMPI and CMPM. The compiler
often chooses the right instruction, so you can write CMP all the time if
you want.


*** DIVS ***

DIVide Signed. The instruction divides a signed (twocomplement) dataregister
with an operand specified as an effective address. The dataregister is
32 bits and the effective address is a word. The result is stored in the
lower 16 bits of the dataregister and the remainder in the upper 16 bits.
Two errors can arise with DIVS:

1. If you try to divide with 0 an interrupt will occur.

2. If the result doesn't fit in 16 bits the dataregister will remain unchanged
   and the V-flag will be set (overflows).

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, x(PC),
                x(PC,xr.s), #x

DATALENGTH: Word

FLAGS:  X - U
        N - S, undef if overflow
        Z - S, undef if overflow
        C - 0
        V - S

SYNTAX: DIVS <ea>,Dn


*** DIVU ***

DIVide Unsigned. The instruction divides an unsigned dataregister with an
operand specified as an effective address. The dataregister is 32 bits and the
effective address is a word. The result is stored in the lowest 16 bits of the
dataregister and the remainder in the upper 16 bits. Two errors can arise with
DIVU:

1. If you try to divide with 0 an interrupt will occur.

2. If the result doesn't fit in 16 bits the dataregister will remain unchanged
   and the V-flag will be set (overflows).

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, x(PC),
                x(PC,xr.s), #x

DATALENGTH: Word

FLAGS:  X - U
        N - S, undef if overflow
        Z - S, undef if overflow
        C - 0
        V - S

SYNTAX: DIVS <ea>,Dn


*** EXT ***

The instruction EXT (Sign EXTend) makes a sign extension, byte to a word
or a word to a longword.
If you extend a byte to a word, bit 7 is copied to bit 15-8. If you extend
a word to a longword, bit 15 is copied to bit 31-16.

ADDRESSMETHODS: Dn

DATALENGTH: Word, Longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: EXT Dn


*** MULS ***

The instruction MULS (MULtiply Signed) multiplies a 16 bits operand in a
dataregister with a 16 bits operand specified as an effective address.
The result is a 32 bits value that is stored in the dataregister. All operands
are signed (twocomplement).

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, x(PC),
                x(PC,xr.s), #x

DATALENGTH: Word

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: MULS <ea>,Dn


*** MULU ***

The instruction MULS (MULtiply Unsigned) multiplies a 16 bits operand in a
dataregister with a 16 bits operand specified as an effective address.
The result is a 32 bits value that is stored in the dataregister. All operands
are unsigned.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, x(PC),
                x(PC,xr.s), #x

DATALENGTH: Word

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: MULU <ea>,Dn


*** NEG ***

The instruction NEG returns the twocomplement of an operand given as an
effective address.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - Clear if the result is zero, else set
        N - S
        Z - S
        C - Same as X
        V - S

SYNTAX: NEG <ea>


*** NEGX ***

The instruction NEGX (NEGate with eXtend) returns the twocomplement from
a binary number with multiprecision.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - Set if loan, else cleared
        N - S
        Z - Set if the result is not zero, else unaffected
        C - Same as X
        V - S

SYNTAX: NEGX <ea>


*** SUB ***

Subtracts two binary operands and stores the result in the destination operand.

Two different methods allowed:

1. Subtract an effective address from a dataregister.
2. Subtract a dataregister from an effective address.

ADDRESSMETHODS: 1) Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                   x(PC), x(PC,xr.s), #x

ADDRESSMETHODS: 2) (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

When using an addressregister as destination, byte is not allowed.

FLAGS:  X - Set if a loan was required from the most significant bit, else 0.
        N - S
        Z - S
        C - Same as X
        V - S

SYNTAX: SUB Dn,<ea>
        SUB <ea>,Dn

When an addressregister is the destination, you use SUBA. Many assemblers
will automatically choose SUBA if you write SUB with an addressregister
as destination.


*** SUBA ***

Binary subtraction from an addressregister. To make it possible to mix
addressoperations with dataoperations, this instruction won't affect any
flags.

ADDRESSMETHODS: Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                x(PC), x(PC,xr.s), #x

The effective address must be the source.

DATALENGTH: Word, longword

SUBA affects always all 32 bits in the destination addressregister.

FLAGS:  Unaffected

SYTNAX: SUBA <ea>,An


*** SUBI ***

Subtracts a constant from an effective address.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - Set if a loan was required from the most significant bit, else 0.
        N - S
        Z - S
        C - Same as X
        V - S

SYNTAX: SUBI #x,<ea>

Most assemblers automatically choose SUBI if the source operand to an SUB
instruction is a constant.


*** SUBQ ***

This instruction subtracts a three bit constant from an effective address.
The instruction is very quick and much shorter than the usual SUB.

ADDRESSMETHODS: Dn, An, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

When using an addressregister as destination, byte is not allowed.

FLAGS:  X - Set if a loan was required from the most significant bit, else 0.
        N - S
        Z - S
        C - Same as X
        V - S

No flags are affected if the destination operand is an addressregister.

SYNTAX: SUBQ #<data>,<ea>

#<data> is a constant between 1 and 8.


*** SUBX ***

The instruction SUBX (SUBtract eXtended) works as SUB but the X flag is
also subtracted. This makes it possible to add big numbers stored in many
bytes (multiprecision).

The instruction have two methods:

1. Subtract a dataregister from a dataregister.
2. Subtract a memory location to another memory location. You must use -(An)
   on both operands then.

ADDRESSMETHODS: Dn, -(An)

DATALENGTH: Byte, word, longword

FLAGS:  X - Set if a loan was required from the most significant bit, else 0.
        N - S
        Z - Cleared if the result is not zero, else unaffected
        C - Same as X
        V - S

The Z flags works in another way now, making it possible to check if a
big number (much bigger than 32 bits) is zero. You must set the zero flag
before making the addition though, shorter than comparing a register with
itself.

SYNTAX: SUBX Dy,Dx
        SUBX -(Ay),-(Ax)


*** TAS ***

The instruction TAS (Test And Set) examines a byte specified with an
effective address. The most significant bit in the byte is set. The
N- and Z-flags are set according to the bytes value before the operation.
The instruction reads, modifies and sets and can't be interrupted.
The instruction is used to synchronize if two or more MPU use the same
memory area. Since TAS can't be interrupted a MPU can mark a location in
the memory to be "busy" before another processor can examine it. If
the operation was interuptable, two processor could examine the same
byte at the same time, and both processor would think the byte was
free to use, which would lead to an error. TAS guaranties that one
processor wins and the other loses. TAS is used by high level langages
to implement "Semaphors"

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

You can use TAS with a dataregister, but then it has nothing to do
with syncronization.

DATALENGTH: Byte

FLAGS:  X - U
        N - S (before the operation)
        Z - S (before the operation)
        C - 0
        V - 0

SYNTAX: TAS <ea>


*** TST ***

The instruction TST examines an operand specified as an effective address,
and finds out if it's zero or negative. The flags are set depending on
the result.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: TST <ea>


                     ------------------------------------
                      2.04  Logical operations
                     ------------------------------------

*** AND ***

The instruction AND performs the logical operation "AND", bit for bit.

1. The source is and effective address, the destination is a dataregister.
2. The source is the dataregister and the destination is the effective address.

ADDRESSMETHODS: 1) Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                   x(PC), x(PC,xr.s), #x
                2) (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: AND <ea>,Dn
        AND Dn,<ea>


*** ANDI ***

Same as AND except that the source is an immediate value.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, SR, CCR

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: ANDI #<data>,<ea>


*** EOR ***

EOR performs an exclusive OR between a dataregister and the memory. EOR
gives the result (binary) 1 if one, and only one, of the operators are 1
(compare with OR). The dataregister must be the source and the effective
address the destination.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENTGH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: EOR Dn,<ea>


*** EORI ***

EORI performs an exclusive OR between an immediate value and an effective
address. EORI gives the result (binary) 1 if one, and only one, of the
operators are 1 (compare with OR). The effective address must be the
destination of course.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, SR, CCR

Operations that uses the statusregister (SR) and the flagregister (CCR) can
only work with word and byte. If you try to change SR you must be in
supervisor mode, else an interrupt occurs. ( use trap #1 to change the mode ) 

DATALENTGH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

If the statusregister or the flagregister is the destination, the flags are
set the same way as any other effective address. If an instruction clears all
bits in the flagregister, the Z flag won't be set (as it should since the
result was 0).

SYNTAX: EORI #<data>,<ea>


*** NOT ***

Returns the onecomplement of an operand specified with an effective address.
The onecomplement is the same as changing all bits in the operand.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: NOT <ea>


*** OR ***

The instruction OR performs the logical operation "OR", bit for bit. There
are two ways to do this:

1. The source is an effective address, the destination is a dataregister.
2. The source is the dataregister and the destination is the effective address

ADDRESSMETHODS: 1) Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l,
                   x(PC), x(PC,xr.s), #x
                2) (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: OR <ea>,Dn
        OR Dn,<ea>


*** ORI ***

Same as OR except that the source is an immediate value.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, SR, CCR

When using SR, the S-bit must be set.

DATALENGTH: Byte, word, longword

FLAGS:  X - U
        N - S
        Z - S
        C - 0
        V - 0

SYNTAX: ORI #<data>,<ea>


                     ------------------------------------
                      2.05  Shift and rotation
                     ------------------------------------

*** ASL ***

Performs an arithmetic shift to the right on a dataregister or a memory
location. Has three possibilites:

1. Shift a dataregister to the left. Number of steps is stored in another
   dataregister. You can shift 1-8 bits this way.
2. Shift a dataregister to the left. Number of steps is an immediate value.
3. Shift a word in the memory one bit to the left.

ADDRESSMETHODS: 3) (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - The last bit that was sent out of the operand. Unaffected if
            number of steps is 0.
        N - S
        Z - S
        C - Same as X
        V - Set if the most significant bit was changed during the operation.
            Cleared else.

SYNTAX: ASL Dx,Dy
        ASL #<data>,Dy
        ASL <ea>


*** ASR ***

Performs an arithmetic shift to the right on a dataregister or a memory
location. Has three possibilites:

1. Shift a dataregister to the right. Number of steps is stored in another
   dataregister. You can shift 1-8 bits this way.
2. Shift a dataregister to the right. Number of steps is an immediate value.
3. Shift a word in the memory one bit to the right.

ADDRESSMETHODS: 3) (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - The last bit that was sent out of the operand. Unaffected if
            number of steps is 0.
        N - S
        Z - S
        C - Same as X
        V - Set if the most significant bit was changed during the operation.
            Cleared else.

SYNTAX: ASR Dx,Dy
        ASR #<data>,Dy
        ASR <ea>


*** LSL ***

Performs a logical shift to the left on a dataregister or a memory
location. Has three possibilites:

1. Shift a dataregister to the left. Number of steps is stored in another
   dataregister. You can shift 1-8 bits this way.
2. Shift a dataregister to the left. Number of steps is an immediate value.
3. Shift a word in the memory one bit to the left.

ADDRESSMETHODS: 3) (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - The last bit that was sent out of the operand. Unaffected if
            number of steps is 0.
        N - S
        Z - S
        C - Same as X
        V - Set if the most significant bit was changed during the operation.
            Cleared else.

SYNTAX: LSL Dx,Dy
        LSL #<data>,Dy
        LSL <ea>


*** LSR ***

Performs a logical shift to the right on a dataregister or a memory
location. Has three possibilites:

1. Shift a dataregister to the right. Number of steps is stored in another
   dataregister. You can shift 1-8 bits this way.
2. Shift a dataregister to the right. Number of steps is an immediate value.
3. Shift a word in the memory one bit to the right.

ADDRESSMETHODS: 3) (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, word, longword

FLAGS:  X - The last bit that was sent out of the operand. Unaffected if
            number of steps is 0.
        N - S
        Z - S
        C - Same as X
        V - Set if the most significant bit was changed during the operation.
            Cleared else.

SYNTAX: LSR Dx,Dy
        LSR #<data>,Dy
        LSR <ea>


*** ROL ***

The instruction ROL rotates a dataregister or a memory operand to the left.
There are three ways to do this:

1. Rotate a dataregister to the left. Number of steps is a constant.
2. Rotate a dataregister to the left. Number of steps is stored in another
   dataregister. You can rotate 1-8 bits this way.
3. Rotate e a word in the memory one bit to the left.

The rotation is done without an extra bit (ie a 8, 16 or 32 bit rotation).
The bit that is rotated from the highest position to the lowest will also
be send to the carry flag.

   C <-- OPERAND <--
      |____________|

ADDRESSMETHODS: (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l
(only when rotating a word in the memory)

DATALENGTH: Byte, word, longword

When rotating in the memory, you can only use word.

FLAGS:  X - U
        N - S
        Z - S
        C - Equal to the bit that was last moved from the operand.
            If steps is zero, the flag is cleared.
        V - 0

SYNTAX: ROL #<steps>,Dy
        ROL Dx,Dy
        ROL <ea>


*** ROR ***

The instruction ROR rotates a dataregister or a memory operand to the right.
There are three ways to do this:

1. Rotate a dataregister to the right. Number of steps is a constant.
2. Rotate a dataregister to the right. Number of steps is stored in another
   dataregister. You can rotate 1-8 bits this way.
3. Rotate a word in the memory one bit to the right.

The rotation is done without an extra bit (ie a 8, 16 or 32 bit rotation).
The bit that is rotated from the lowest position to the highest will also
be send to the carry flag.

      --> OPERAND --> C
      |____________|

ADDRESSMETHODS: (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l
(only when rotating a word in the memory)

DATALENGTH: Byte, word, longword

When rotating in the memory, you can only use word.

FLAGS:  X - U
        N - S
        Z - S
        C - Equal to the bit that was last moved from the operand.
            If steps is zero, the flag is cleared.
        V - 0

SYNTAX: ROR #<steps>,Dy
        ROR Dx,Dy
        ROR <ea>


*** ROXL ***

The instruction ROXL (ROtate Left with eXtend) rotates a dataregister or a
memory operand to the left. There are three ways to do this:

1. Rotate a dataregister to the left. Number of steps is a constant.
2. Rotate a dataregister to the left. Number of steps is stored in another
   dataregister. You can rotate 1-8 bits this way.
3. Rotate e a word in the memory one bit to the left.

The rotation is done with an extra bit (ie a 9, 17 or 33 bit rotation).
The most significant bit is rotated to the carry flag and to the extra
flag. The bit at the extra flag will be rotated to the least significant
bit in the operand.

   C <-- OPERAND <--
      |            |
      |-> X ->-----|


ADDRESSMETHODS: (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l
(only when rotating a word in the memory)

DATALENGTH: Byte, word, longword

When rotating in the memory, you can only use word.

FLAGS:  X - The last bit that was rotated from the operand. Unaffected
            if rotation steps was zero.
        N - S
        Z - S
        C - Same as X
        V - 0

SYNTAX: ROXL #<steps>,Dy
        ROXL Dx,Dy
        ROXL <ea>


*** ROXR ***

The instruction ROXR (ROtate Left with eXtend) rotates a dataregister or a
memory operand to the right. There are three ways to do this:

1. Rotate a dataregister to the right. Number of steps is a constant.
2. Rotate a dataregister to the right. Number of steps is stored in another
   dataregister. You can rotate 1-8 bits this way.
3. Rotate a word in the memory one bit to the right.

The rotation is done with an extra bit (ie a 9, 17 or 33 bit rotation).
The least significant bit is rotated to the carry flag and to the extra
flag. The bit at the extra flag will be rotated to the most significant
bit in the operand.

    -- OPERAND ----> C
    |            |
    |----<- X <--|

ADDRESSMETHODS: (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l
(only when rotating a word in the memory)

DATALENGTH: Byte, word, longword

When rotating in the memory, you can only use word.

FLAGS:  X - The last bit that was rotated from the operand. Unaffected
            if rotation steps was zero.
        N - S
        Z - S
        C - Same as X
        V - 0

SYNTAX: ROXR #<steps>,Dy
        ROXR Dx,Dy
        ROXR <ea>

                     ------------------------------------
                      2.06  Bitmanipulation
                     ------------------------------------

*** BCHG ***

This instruction will change a bit in an operand specified by an effective
address. The Z-flag (the only flag affected) will be set as the bit was
before the change! The bit number is stored in a dataregister or is an
immediate address.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, longword

FLAGS:  Z - Set if the bit was 0 before the change, else cleared.
        All other flags unaffected.

SYNTAX: BCHG Dn,<ea>
        BCHG #<data>,<ea>


*** BCLR ***

This instruction will clear a bit in an operand specified by an effective
address. The Z-flag (the only flag affected) will be set as the bit was
before the change! The bit number is stored in a dataregister or is an
immediate address.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, longword

FLAGS:  Z - Set if the bit was 0 before the operation, else cleared.
        All other flags unaffected.

SYNTAX: BCLR Dn,<ea>
        BCLR #<data>,<ea>


*** BSET ***

This instruction will set a bit in an operand specified by an effective
address. The Z-flag (the only flag affected) will be set as the bit was
before the change! The bit number is stored in a dataregister or is an
immediate address.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte, longword

FLAGS:  Z - Set if the bit was 0 before the change, else cleared.
        All other flags unaffected.

SYNTAX: BSET Dn,<ea>
        BSET #<data>,<ea>


*** BTST ***

This instruction will test a bit in an operand specified by an effective
address. The Z-flag (the only flag affected) will be set as the bit was
before the change! The bit number is stored in a dataregister or is an
immediate address.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l, x(PC),
                x(PC,xr.s)

DATALENGTH: Byte, longword

FLAGS:  Z - Set if the bit was 0 before the change, else cleared.
        All other flags unaffected.

SYNTAX: BTST Dn,<ea>
        BTST #<data>,<ea>


                     ------------------------------------
                      2.07  BCD-instructions
                     ------------------------------------

*** ABCD ***

Adds two byte in BCD-form (Binary Coded Decimal). The destination operand
is replaced with the sum of the source and the destination operand.

ADDRESSMETHODS: Dn, -(An)

Only two methods allowed:

1. Add dataregister to another dataregister (Dn to Dn)

2. Add memory to memory. This is used when you add BCD numbers stored in
   many bytes. You must start at the highest address (the least significant
   byte in the BCD number) and go upwards. The X flag is set if the addition
   results in a carry, which is added to the next byte.

DATALENGTH: Byte

FLAGS:  X - Set if carry from the most significant BCD digit.
        N - undef
        Z - Cleared if the result is NOT zero. Unaffected else.
        C - Same as X
        V - undef

SYNTAX: ABCD Dx,Dy
        ABCD -(Ax),-(Ay)


*** NBCD ***

The instruction NBCD (Negate BCD) negates a BCD-number. The method used
is tencomplement. The tencomplement to 01 is 99 (1+99=10000), to 26 is 74
(26+74=100) and so on.
 The X flag is added to the tencomplement which is the loan from the
previous BCD calculation (multiprecision). A normal serie of BCD instructions
starts with the X flag cleared and the Z flag set.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte

FLAGS:  X - Set if a loan was required when subtracting, else cleared
        N - undef
        Z - Cleared if the result was 0, else unaffected
        C - Same as X
        V - undef

SYNTAX: NBCD <ea>


*** SBCD ***

The instruction SBCD (Subtract BCD with extend) subtracts two bytes
in BCD-form. The difference (destination - source - X flag) is stored
in the destination register.

ADDRESSMETHODS: Dn, -(An)

There are two ways to use the instruction:

1. Subtract a dataregister from a dataregister (addressmethod Dn). The
   lower byte in the source register is subtracted from the lower byte
   in the destination register, where the answer is stored.

2. Subtract memory from memory. This way, you can subtract big numbers
   stored in many bytes. Since you only can use -(An) you must start
   on the highest byte (the least significant digits in the BCD number)
   and work down. If there is a carry, the X bit is set, which will be
   subtracted from the next byte.

DATALENGTH: Byte

FLAGS:  X - Set if a loan was required from the most significant BCD digit.
        N - undef
        Z - Cleared if the result was 0, else unaffected
        C - Same as X
        V - undef

The Z flag is cleared if the result is not 0. This way, you can see if
the answer after a serie of subtractions is zero or not. First, you have
to set the Z flag (easiest done by comparing a register with itself). Then
do the subtractions, and if the Z flag is set, the BCD number is zero.

SYNTAX: SBCD Dx,Dy
        SBCD -(Ax),-(Ay)

                     ------------------------------------
                      2.08  Programcontrol
                     ------------------------------------

*** Bcc ***

This instruction will cause a branch in the program if certain flags are set.
There are fifteen ways of checking the flags. Each of them have a symbol
on two letters which will replace the "cc" in "Bcc".

BCC  Branch Carry Clear      - Branch if the C-flag is 0.
BCS  Branch Carry Set        - Branch if the C-flag is 1.
BEQ  Branch EQual            - Branch if the Z-flag is 1.
BNE  Branch Not Equal        - Branch if the Z-flag is 0.
BGE  Branch Greater or Equal - Branch if N and V are equal.
BGT  Branch Greater Than     - Branch if N and V are equal and Z=0.
BHI  Branch HIgher than      - Branch if both C and Z are 0.
BLE  Branch Less or Equal    - Branch if Z=1 or if N and V are different.
BLS  Branch Lower or Same    - Branch if C=1 or Z=1.
BLT  Branch Less Than        - Branch if N and V are different.
BMI  Branch MInus            - Branch if N=1.
BPL  Branch PLus             - Branch if N=0.
BVC  Branch V Clear          - Branch if V=0
BVS  Branch V Set            - Branch if V=1.
BRA  BRanch Always

Some conditions are pretty similiar. BGE, BGT, BLE, BLT should be used
when using signed integers and BHI and BLS when using unsigned integers.

ADDRESSMETHODS: No special. You specify a label, which the compiler will
                change to a relative address, byte or word depening on how
                far you will jump.

DATALENGTH: Byte, word

FLAGS:  Unaffected

SYNTAX: Bcc.B <label>
        Bcc.W <label>

You don't have to (you shouldn't) add .B or .W, the compiler will choose
the best syntax.


*** BSR ***

Branch to SubRoutine. This instruction will push the address to the next
instruction on the stack, then branch to the label specified in the
instruction (a relative address). Used to call subroutines in your own
programs.

ADDRESSMETHODS: No real addressmethod. The label is a relative address.

DATALENGTH: Byte, word

FLAGS:  Unaffected

SYNTAX: BSR.B <label>
        BSR.W <label>

You shouldn't add .B or .W, the compiler will choose the best syntax.


*** DBcc ***

DBcc is an instruction that quits loops. The instruction is very similiar to
Bcc (same conditions are used, see above for the different conditions) except
that the first operand is a dataregister that will be decreased with one
until is reached -1, then the loop stops. The loop can also quit if the
flags are set correctly (specified with the condition). You often use
DBRA (Never quit) that will quit the loop when the dataregister has reached
-1. If you want the loop the be looped 10 times, you should set a dataregister
to 9 (since it ends at -1, not 0).

ADDRESSMETHODS: No real addressmethod.

DATALENGTH: Word

FLAGS:  Unaffected

SYNTAX: DBcc Dn,<label>


*** JMP ***

JMP (JuMP) is used to move the program control to an effective address. It
really works as MOVE.L xxx,PC, since it changes the program counter to an
effective address (calculated).

ADDRESSMETHODS: (An), x(An), x(An,xr.s), x.w, x.l, x(PC), x(PC,xr.s)

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: JMP <ea>

Note that JMP should never be used in a fargo program.

*** JSR ***

JSR (Jump to SubRoutine) works as JMP except that before the jump is made,
the address to the instruction after JSR is pushed to the stack, so you
can return with the instruction RTS.

ADDRESSMETHODS: (An), x(An), x(An,xr.s), x.w, x.l, x(PC), x(PC,xr.s)

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: JSR <ea>


*** RTR ***

The instruction RTR (ReTurn and Restore) pops the flags and the program-
counter from the stack. First a word is popped from the stack and the
lower byte of that word is stored in the flagregister. The higher byte
is ignored. Then a longword is popped into the programcounter. The
stackpointer will be increased with six.

ADDRESSMETHODS: None

DATALENGTH: -

FLAGS:  The flags is set according to the first word that is popped from the
        stack.

SYNTAX: RTR


*** RTS ***

The instruction RTS (ReTurn from Subroutine) does the opposite to the
instructions BSR (Branch to SubRoutine) and JSR (Jump to SubRoutine).
The longword on top of the stack is stored in the programcounter. The
instruction is used when ending a subroutine. The execution will return
to the instruction that follows the last JSR- or BSR- instruction.

ADDRESSMETHODS: None

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: RTS


*** Scc ***

This instruction sets all bits in a byte (effective address) if a
condition is true, else all bits are cleared.

The conditions can be CC,CS,EQ,GE,GT,HI,LE,LS,LT,MI,NE,PL,VC,VS (for
these, check the Bcc instruction for what they mean), SF (always false),
ST (always true).

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x.l

DATALENGTH: Byte

FLAGS:  Unaffected

SYNTAX: Scc <ea>


                     ------------------------------------
                      2.09  Systemcontrol
                     ------------------------------------

*** CHK ***

CHecK register against bounds. Is often used in high level languages to check
if variables are in range. The lowest 16 bits of a dataregister are compared
with an effective address. If the result is less than 0 (if bit 15 is 1) or
greater than the limit, the result will be a CHK-interrupt.

ADDRESSMETHODS: Dn, (An), (An)+, -(An), x(An), x(An,xr.s), x.w, x(PC),
                x(PC,xr.s), #x

DATALENGTH: Word

FLAGS:  X - U
        N - Set if the dataregister is less than zero, cleared if the
            dataregister is greater than the higher limit. Else undefined.
        Z - U
        C - U
        V - U

SYNTAX: CHK <ea>,Dn


*** MOVE USP ***

The instruction MOVE USP transfer the usermode stackpointer to or from an
addressregister. The instruction requiers that you are in supervisor mode.
Since the 68k processor has two stackpointers, this instruction is necessary
when a supervisor program wants to access the usermode stackpointer.

ADDRESSMETHODS: An

DATALENGTH: Longword

FLAGS:  Unaffected

SYNTAX: MOVE USP,An
        MOVE An,USP


*** RESET ***

This instruction restores all external units.

ADDRESSMETHODS: None

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: RESET


*** RTE ***

The instruction RTE (ReTurn from Exception) is used to put data in both
the statusregister and the program counter with the same instruction. This
instruction is necessary when an operatingsystem that is working in
supervisor mode must leave the control to an application in usermode.
The new contents in the statusregister and the programcounter is popped
from the stack. First, a word is popped into the statusregister, then
a longword is popped into the programcounter. Thus, the stackpointer is
increased with six.
This instructions requires that the S bit is set in the statusregister when
the instruction is executed. Since the statusregister is changed after
the instruction, it's possible that the processor be in usermode then.

ADDRESSMETHODS: None

DATALENGTH: -

FLAGS:  All flags is popped from the stack.

SYNTAX: RTE


*** STOP ***

This instruction enables interrupts and waits for an interrupt. The
instruction requires that the processor works in supervisor mode.
An immediate 16 bit data value is stored in the statusregister. Bit
13 in that data must be set (that will be the S bit after the instruction).
Otherwise, an interrupt will occur since you're in usermode (you
must be in supervisor mode before and after this instruction).

ADDRESSMETHODS: -

DATALENGTH: -

FLAGS:  The flags will be bit 0-5 in the immediate data

SYTNAX: STOP #<data>


*** TRAP ***

The instruction TRAP pushes the programcounter and the statusregister
on the supervisor stack, switches to supervisor mode and the programcounter
is given a new value taken from one of the sixteen vectors, given by a
four bit datavalue.
The instruction is used in applications to call a supervisor program (an
OS for example) without knowing exactly where in the memory the OS is.

ADDRESSMETHODS: -

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: TRAP #<vector>

The vector used by TRAP is stored at $80+4*vector (absolute address).


*** TRAPV ***

The instruction TRAPV examines if an overflow has arised. If it hasn't
(the V flag is 0), nothing happens. If it has, the programcounter and
the statusregister is pushed on the stack, and the programcounter will
be given a new address, stored at the absolute address $1C. The MPU
is set to supervisor mode.
The instruction is often used by highlevel languages.

ADDRESSMETHODS: -

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: TRAPV


                     ------------------------------------
                      2.10  Other instructions
                     ------------------------------------

*** ILLEGAL ***

This isn't a real instruction 68k instruction. It will cause an interrupt
(Illegal instruction) on all 68k CPUs. Often used as breakpoint in debuggers.

ADDRESSMETHODS: None

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: ILLEGAL


*** NOP ***

The instruction NOP (No OPeration) makes nothing during one instruction.
Nothing happens except that the program counter is set to the next instruction.
NOP is used to make small delays (VERY small delays, to let hardware parts
to act) and to create empty space in the program which can later be used
for changes.

ADDRESSMETHODS: None

DATALENGTH: -

FLAGS:  Unaffected

SYNTAX: NOP


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

                            3.0 PROGRAMMING STUFF

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


                           -----------------------
                            3.01 THE VIDEO MEMORY
                           -----------------------

Maybe the most important piece of information a game programmer wants: How
do I do graphics!?!? Well, if you know how the video memory works on the
TI-85, it'll be easy. It's stored the same way! 8 pixels/byte (since it's
just black&white graphics, one pixel=one bit) and the top left corner
is at tios::main_lcd. Then it goes from left to right, up to down. Each row takes
30 bytes (30*8=240) and since it's 128 rows the video memory is $0F00 bytes
long, ie it ends at tios::main_lcd+$F00.

You should be able to handle the flib functions for putting pixels and such.

For grayscale graphics, there are examples for it. Looking in the source
for gray4lib.asm should be enough though. It works just as if there were
two video memories, ie two bit planes. This is cleanly explained in
lesson_3.txt.


                            ----------------------
                             3.02  Highscores etc
                            ----------------------

It's very simple to create highscores in games or other things that you want
to be saved until you run the game/program the next time. Since Fargo programs
doesn't have a checksum, you can change in the source (which you actually
do all the time when changing the "temporary" variables) how much you like.

This means it's easy to do a highscore table or so, just make a highscore
label and store the highscore there. Just don't reset it when starting the
game.
However, you can' t create a handle for a highscore table (that would
be good if the highscore had >10 entries where you could enter your name
and so, since that will take at least 100 bytes) since when you destroy a
handle, the content will be destroyed (or overwritten later), and you should
NOT exit the program without destroying all created handles, see 1.10 Handles.
See lesson_2.txt section II to get a clean routine for highscores...


                                --------------
                                 3.03  Arrays
                                --------------

Arrays, vectors, matrices, lookuptables. Call it what you want. It's the
same thing. In highlevel languages it's very easy to use arrays, just
but brackets after the variable and put an index inbetween. It's not that
simple in assembly, but still simple when you know how to do.

Let's say we want to have an one dimensional array with 100 elements, all
words. At the end of the program in the variable declaration we declare
it like this:

 table   ds.w 100

There we have it, 200 bytes allocated for storaged. It's VERY important that
the offset to the table is an even address, else the calc will crash when we
try to read/store in the array. To be sure it is, put the table before all
variables that are defined as bytes. ( or use the "even" assembler directive )

To store a word at a certain place in the table, here is the simpliest way:
(d0 is the word to store, d1 is where in the array, 0-99)

 lea     table(PC),a0  ; Now A0 points to the table
 lsl.w   #1,d1         ; Since we use words, we must multiplicate the index
                       ; with 2 (each element is two bytes)
 move.w  d0,0(a0,d1)   ; Store the word d0 at 0+a0+d1.

Done! Simple. If you want to read a word from the array, just swap the
two operands in the last move instructions.

If we have a two dimensional array, it's a bit harder (not much). Let's
say the array is 50x50, each element is a word. The table is declared as

 table   ds.w 50*50

And here's the routine to store the word d0 at row d1, col d2:

 lea     table(PC),a0  ; Let A0 point at the table
 mulu    #100,d1       ; One row is 100 bytes (50 words). We must use
                       ; MULU to get the right offset. If each row was
                       ; 128 bytes, we could have shifted instead (faster).
 adda    d1,a0         ; Add the rowoffset to the pointer
 lsl.w   #1,d2         ; Multiplicate the column with 2 (same reason as above)
 move.w  d0,0(a0,d2)   ; And store the word

When you use these routines, you MUST BE SURE that the upper word of D1
and D2 is cleared, else it won't work! To be sure about that, use EXT.L
or load the row and col with MOVE.L (or MOVEQ if possible) to erase the
upper word.


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

                              4.0 MISCELLANEOUS

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



                           -----------------------
                            4.01  Version history
                           -----------------------

    0.5  - Section 2.0 Instruction Summary not finished  (24 nov 96)
    0.6  - All instructions to D finished (27 nov 96)
    1.0  - Finally done! Instruction Summary finished, created 3.00
           Programming Stuff and added some more sections, library & arrays
           (10 dec 96)
    1.1  - Corrected to match fargo II file listing, corrected some errors
           (link and unlink mostly ). Added some stuff to the system byte
           section. (29 june 98)
           Corrections made by mathieu lacage <hmlacage@aol.com>.
           This guide is now distributed and designed to be distributed
           with "tutorial.zip" available at ticalc.org. 
    1.1.1- Corrected many spelling errors and small errors, added a few things
           Corrections made by mathieu lacage <hmlacage@aol.com>. (20 july 98) 


                              -----------------
                               4.02  Greetings
                              -----------------

 * David Ellsworth,
   Rob Taylor &
   Dan Eble             - FARGO!!! incl. sources, documents and more

 * Jonas Minnberg       - Fantastic Fargo programs!

 * All Fargo coders     - We're not many, but this guide will hopefully
                          bring more people into the light...


 * Steve Williams       - For the GREAT book, "Programming the 68000"
                          (I've learned almost all 68k programming from it)

 * The ppl at #fargo +
   #calc-ti (EFnet)     - For supporting me in writing this guide and
                          chatting (and the telephone bill...)


Many more to come...


                          -------------------------
                           4.03  How to contact me
                          -------------------------

The quickest, the best, the safest (???) way:

  Email......: yarin@acc.umu.se

The slowest way (but good when sending money :-) ):

  Snailmail..: Jimmy Mardell
               Plommonvagen 21
               904 36 Umea
               SWEDEN

The coolest way, and most "live" way:

  IRC........: Yarin   EFnet:  #ti          (ex irc.gate.net)
                       IRCnet: #synthare    (ex irc.stealth.net)

The sportiest (surfing) way:

  WEB........: http://www.acc.umu.se/~yarin/




----------- 68000 GUIDE FOR FARGO PROGRAMMERS ------- LAST UPDATE: 98-07-20-

Back to Programming

Personal tools