首页
社区
课程
招聘
[下载]68000的指令集(英文版的)
发表于: 2009-5-15 11:44 11150

[下载]68000的指令集(英文版的)

2009-5-15 11:44
11150
在网上找了好久才找到,也许太老了。
需要的就下载吧!
总共2个文件,一个是被分割成3个rar了

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 221
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
The Guide to 68000 Assembly Language
From Atari Forum Wiki
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......: [email]yarin@acc.umu.se[/email]

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-
2009-5-15 11:44
0
雪    币: 221
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
历史
摩托罗拉公司于1976年启动MACSS项目(Motorola Advanced Computer System on Silicon,摩托罗拉硅晶高级计算机系统),打算开发一款与以前产品完全不兼容的全新微处理器。根据计划,新CPU应该是对当时摩托罗拉主流8位CPU6800的一个高端互补产品,而不会考虑两者间的兼容性。不过,当68000设计出来后,它还是被保留了一个可兼容6800外设的总线协议模式,并且专门有8位数据总线的产品被生产出来。当然,设计人员还是更在意于其向后兼容性,这为68000确立在32位CPU领域的领先优势奠定了基础。比如,68000使用32位寄存器和内部总线,尽管其本身的结构很少直接操作长字。小型计算机诸如PDP-11和VAX—二者采用了类似的微编码—对68000的设计有深刻的影响。

在20世纪70年代中期,8位微处理器生产商纷纷竞争导入下一代16位CPU。国家半导体在1973年到1975年间首先开发出了IMP-16和PACE,但其速度并不理想。英特尔公司于1977年推出8086,迅速受到欢迎。此时,为确保竞争上的领先,摩托罗拉认识到其MACSS项目必须跳过16位系统,而直接推出16/32位混合型CPU。到1979年,摩托罗拉68000,即MC68000,才告姗姗来迟。由于比8086晚两年,其晶体管数目更多,并因其易用性得到了好评。

最初的MC68000使用3.5微米HMOS技术(即高性能N通道金属氧化物半导体,CMOS的前身)制造。1979年发布了工程样品,次年产品型面世,速度有4、6、8、10兆赫兹多种。最快的16.67MHz版本到80年代末才面市。

MC68000在早期得到了很多高端产品的青睐。在升阳公司的Sun workstation等多种Unix工作站中,MC68000一度占统治地位。市场领先的其他一些计算机,包括Amiga(阿米加)、Atari ST(雅达利ST)、Apple Lisa (苹果Lisa)和 Macintosh(麦金托什),以及第一代激光打印机,如苹果公司的LaserWriter,都使用MC68000。1982年,摩托罗拉进一步更新了MC68000的指令集以支持虚拟内存,并使其能够满足由Popek和Goldberg于1974年提出的虚拟化标准。

为支持低成本系统和使用较少内存的应用,摩托罗拉于1982年还推出了面向8位外部数据总线的MC68008。1982年以后,摩托罗拉开始把更多的注意力投向68020和88000。

其他制造商
由日立公司设计,1985年两公司联合推出了使用CMOS技术的68HC000。68HC000的速度有8到20MHz多个版本。尽管除了使用CMOS电路,68HC000与基于HMOS的MC68000完全一致,但正是因此其能耗得到大幅下降。MC68000在25摄氏度环境下能耗大约为1.35瓦,而8MHz的68HC000则为0.13瓦,较高频率的版本则能耗也相应提高(HMOS技术则不同:其在CPU空闲时仍会耗电,所以功耗与频率基本无关)。后于1990年摩托罗拉又推出了MC68008的CMOS版本,并将其改进为可兼容8/16位两种总线模式。

其他HMOS版68000的生产商包括:Mostek、Rockwell(洛克维尔)、Signetics、Thomson(汤姆逊)和东芝。东芝也生产CMOS版68000(TMP68HC000)。

应用
68000首先被应用于许多高端产品中,如多用户微型计算机WICAT 150及阿尔法微系统的一些早期计算机等。单用户工作站如惠普公司的HP 9000/200、太阳微系统的Sun-1;图形终端如DEC的VAXstation 100和Silicon Graphics的IRIS 1000均使用68000。许多Unix系统也开始使用68K系列CPU。

在80年代中期,68000又成为首先应用于个人/家庭计算机的CPU。先后有苹果的Apple Lisa与麦金托什、Amiga的海军准将(Commodore)、雅达利ST及夏普的Sharp X68000采用68000。

68000最主要的成功在于控制器领域。早在1981年Imagen公司就把68000用作其激光打印机Imprint-10外部控制器的CPU。惠普于1984年发布的第一款LaserJet打印机亦使用一片8MHz的68000作为内置控制器。类似的基于68000的整合控制器也被广泛用在其他多款打印机中。到90年代,68000仍在许多低端打印机中被使用。

除了传统商业和家用计算应用,68000在工业控制系统中也取得了巨大成功。Allen-Bradley、德州仪器及西门子公司生产的可编程逻辑控制器(PLC)即使用68000。一般来说,这类工业系统的用户更重视产品的可用性,而不是向家庭用户一样过于在意其是否过时。所以,仍有许多使用68000的系统,在被安装二十多年后,在生产一线提供着持续而可靠的服务。

随着技术的进步,68000在计算机单机市场渐被淘汰,但其应用仍活跃于消费和嵌入式领域。游戏机制造商使用68000作为许多街机和家用游戏机的处理器。雅达利在1983年推出的Food Fight便是使用68000的代表街机游戏。世嘉的System 16、卡普空的CPS-1和CPS-2以及SNK的Neo Geo也都使用68000。到了90年代,尽管街机游戏开始使用更加强大的CPU,68000仍被用作声音控制器。

在80年代末到90年代初,一些游戏机厂商使用68000作为家用游戏平台的中央处理器。这包括世嘉的Mega Drive(MD)和Neo Geo家用版。后来,68000还在世嘉的32位CPU游戏机Sega Saturn中用作声音控制器。

基于68000的683XX系列微控制器则广泛应用于许多应用领域中,包括网络和电话设备、电视机机顶盒、实验室与医疗设备等。思科、3com等公司曾在他们生产的通讯设备中使用MC68302及其衍生产品。Palm公司曾使用DragonBall系列CPU(68K系列的后续)作为其PDA的处理器,直到基于RISC的ARM处理器开始统治PDA市场。此外,AlphaSmart公司在其便携式文字处理器中使用DragonBall。

德州仪器在一些高端图形计算器,如TI-89和TI-92中,使用68000。这些设备早期使用以68EC000为内核的专门化微控制器,后来则改用封装好的MC68SEC000。

作为微控制器内核
在被纯32位CPU取代后,68000开始被用作许多微控制器的内核。1989年,摩托罗拉发布了MC68302通讯处理器。两年后又推出独立处理器芯片MC68EC000。1996年的MC68SEC000便使用了这款芯片。

1996年摩托罗拉停产HMOS MC68000和MC68008,但其分离出来的半导体部门,飞思卡尔公司,仍在生产MC68HC000等68K家族系列产品。68000架构的后代,680x0、CPU32以及Coldfire系列,也仍在生产。

架构

地址总线
68000地址总线为24位,故支持16MB最大物理内存。在使用32位长字对地址进行存储和计算时,高位的一个字节会被自动忽略。这种设计使得其具备相当的向前兼容性,可以直接运行为后续的纯32位CPU编写的软件。也因此,根据现今的定义,68000应称得上是一款32位CPU。摩托罗拉使用32位内部总线的目的在于希望能够在68000上编写可以被将来的后续产品直接使用的软件,而相关指令不必作位数上的调整。

然而,编程人员还是有可能编写出无法与后续产品兼容的软件。倘若这种24位软件丢弃高位字节,或将该字节用作寻址以外的目的,它就有可能在32位68K系列CPU上运行失败。这就是说,对于希望支持向前兼容的软件,必须始终使用32位长字寻址,并且将最高位字节置零。

内部寄存器
68000包含8个32位通用寄存器(D0-D7),及8个32位地址寄存器(A0-A7)。最后一个地址寄存器,即A7,也作为标准栈指针使用,在编程中可以使用SP作为同义词。这组寄存器在规模上恰到好处:既可以对中断快速反应(只有十多个寄存器要保存),也有足够的寄存器来进行快速计算。

尽管两种寄存器并存有时会比较麻烦,但在实践中并非难于掌握。据称,这还使得CPU的设计者们可以通过对地址寄存器组使用辅助计算单元,从而实现较高程度的并行机制。

存储内容高位字节在前(Big Endian模式),与x86相反。

状态寄存器
68000比较、算术和逻辑操作会在状态寄存器SR的低端字节(又称CCR)中设置一些标志位,以供之后的条件跳转使用。这些标志位是:得零(Z)、进位(C)、溢出(V)、扩展(X)、负数(N)。尽管许多时候值是相同的,X与C依然是两个不同的标志位。这就允许算术、逻辑和移位操作的多余位与逻辑控制/连接造成的进位区别开。

指令集
68000的指令集基本上是正交的。大部分指令被划分成操作和地址模式两部分,并且大部分地址模式都对几乎全部指令可用。这种近似正交性在编程人员当中毁誉参半。

编程者会清楚地发现,他/她所书写的指令可能被汇编成几种不同的二进制操作码。这实际上是一种不错的妥协:一方面,在便利性上与纯粹的正交指令系统相仿;一方面,CPU设计者可以有更多的自由来设计操作码表。

对于一台16位时代的机器而言,由56条指令构成的最小指令集仍显巨大。此外,许多指令和寻址模式会在指令后边加入地址/寻址模式码。

许多设计者确信MC68000体系结构应基于成本考量使用较精简的指令码,特别是使用编译器自动生成时。这种认识为对其设计上的成功加分不少,并且使之成为一种经久不衰的体系结构。这一信条持续地保证了整个系列指令集的设计优势,直到ARM体系结构引入同样精简的Thumb指令集。

特权级
68K系列CPU包含两个特权级。超级用户(supervisor)模式和用户(user)模式。后者相比于前者只是禁用了中断级控制。中断总会使CPU进入超级用户态。超级用户标志位存储于状态寄存器SR中,并对用户可见。

超级用户态下会有一个分离的栈指针用于中断处理。

中断
68000可以识别7级中断,从级别1到级别7。7级中断严格按优先级排列,一个高级中断总是能嵌套于一个低级中断。可以使用专门的特权指令在SR内设置最小中断级别,从而屏蔽所有小于此级别的中断。但如果设置为0,表示不接受中断。级别7不可被屏蔽,即NMI。级别1总是可以被高级中断打断。

硬件中断源将中断信号以编码方式通过三条输入线传送给CPU。一般会使用专门的中断控制器来汇总各外部设备,并将中断信号按级编码与CPU硬连。中断控制器可以使用简单如74LS148优先级编码器,复杂如MC68901多功能外设(支持可编程中断控制、通用异步收发装置、定时器及并行输入输出等)等各种电路模块。

在内存低1K位置存储中断向量表,共支持256条中断向量。部分中断向量有特殊用途:向量1为初始栈地址;向量2为初始代码地址;向量3到15用于错误报告,包括总线错误、寻址错误、非法指令、除零异常、优先权违反等。从向量24起处理真正的中断,包括伪中断、针对级别1到级别7的默认处理向量,多达15个自陷向量,以及用户定义向量。

由于必须在重启时保证向量1和2的内容有效,所以68000系统通常包含在地址底部使用非易失性存储器(如ROM)来存储一些例程向量和启动代码。但是,一个通用计算机的操作系统会期望在运行时改变向量内容。解决办法是将ROM内的向量指向RAM的分支表,或使用早期在8位CPU中广泛使用的换页技术(Bank switching)。

由于包含一条非特权指令MOVE from SR,允许一般用户只读地访问某些特权状态,68000并未完全满足波佩克与戈德堡虚拟化需求。该需求指出了为构建某一CPU之等价虚拟机而对CPU提出的若干要求。

MC68000对虚拟内存缺乏方便的支持。一款支持虚拟内存的CPU应能在内存访问失败后自陷并恢复。不过,68000确实提供了一个总线错误异常来使CPU自陷,尽管还不能保存足够的状态信息以便于异常处理之后的恢复。为此,一些Unix工作站通过使用两块68000来解决虚拟内存问题。两块CPU的运行时钟存在相位差。当第一块遇到寻址异常后,特殊的硬件会设法向第二块发出中断,以防止其也访问错误地址。中断例程在第二块CPU上处理完内存换页后,会按之前的状态重启第一块CPU,从而再次使两CPU同步。

不过,以上这些问题在MC68010被彻底解决。在MC68010中,总线异常和地址错误均会使大量状态信息压入系统栈,以便于之后的恢复。MOVE from SR也被修正为特权指令。原本用于访问SR低端字节的代码可由新指令MOVE from CCR取代。

指令集细节

标准寻址模式
68000提供多种寻址模式,并统称为有效寻址(EA)。在CPU参考手册中,经常会有诸如MOVE <ea>,<ea>这样的表记方式。这表示在目的操作数和源操作数上可分别使用一种(但通常不是全部)有效寻址。

寄存器直接寻址
数据寄存器直接寻址,如D0。
地址寄存器直接寻址,如A0。通常不使用A7。
寄存器间接寻址
简单间址,如(A0)。先取得A0所存储的地址,再在内存中该地址处取出数据。
自增间址,如(A0)+。只能用于源操作数域。先取得A0所存储的地址,再在内存中该地址处取出数据,然后A0的内容(地址)自增一定长度(因指令后缀而定)。这个操作其实相当于x86中的出栈指令POP(注意栈的方向和内存方向相反)。在这里,A0被用作一个用户自定义的栈指针,与系统使用的A7/A7'不同。
自减间址,如-(A0)。只能用于目操作数域。先取得A0所存储的地址,再在内存中该地址处存入数据,然后A0的内容(地址)自减一定长度(因指令后缀而定)。这个操作其实相当于x86中的入栈指令PUSH。
偏移间址,如2AFF(A0)。前边的偏移量为16位。实际取得的地址为(A0)+2AFF。
加索引的偏移间址,如E3(A0, D0)。前边的偏移量为8位。实际取得的地址为(A0)+(D0)+E3。
程序计数器位移
长位移,如2AFF(PC)。前边的偏移量为16位。PC变为(PC)+2AFF。
短位移,如E3(PC, D0)。前边的偏移量为8位。PC变为(PC)+(D0)+E3。
绝对内存寻址
直接使用内存地址值,如$4000,表示目标地址在内存地址为4000处。注意$表示后边所跟数字为16进制,%表示2进制。
在实际编程中,可以使用代码中的标号来充当内存地址值。汇编器会自动翻译为数字地址。
注意不应与立即数混淆。使用立即数时应在值前再加一个#。$4000表示16进制地址4000;#$4000表示16进制立即数4000;4000表示10进制地址4000;#4000表示10进制立即数4000。

指令后缀
大部分指令都有表示操作长度的后缀:.B、.W或.L,分别表示这一操作在字节(8比特)上、字(16比特)上或长字(32比特)上进行。运算的过程和结果都会受到后缀的影响。在运算过程中,只有属于操作长度范围的部分才会参与运算。比方说,执行MOVE.B D2,D1会把D1的最低一字节复制到D2的最低一字节处,而两者的其余字节均不受影响。对于CCR,各标志位的值会由操作长度的最高有效位决定。如果某次ADD.B使得结果的第7Bit位为1,则CCR的N位会置1;如果某次ADD.L使得结果的第7Bit位为1,并且第15Bit不为1,则CCR的N位不会置1。在后一种情况下,CCR的N位只受第15Bit,即一个字的最高有效位影响。另一个例子是在自增/自减寻址中,自增/自减的长度因操作后缀而异。如果操作为MOVE.B,则自增/自减1;W为2;L为4。

常用指令
大部分68000的指令都是二元的。目的操作数在前,源操作数在后。

移动指令
MOVE:标准移动指令。另有一些其它移动指令供选择:MOVEA(移动到地址寄存器An,不会影响CCR,但后缀不可为.B)、MOVEQ(移动一个8位数到目标寄存器,因为可将数值直接写入指令故称快速移动)、MOVEM(移动寄存器组到指定堆栈,多用于中断/子程序处理的第一步)等。
LEA:移动一个地址值到目标寄存器。LEA $2000,A0表示将A0的值设为16进制的2000。应注意此时不加立即数标志#。
LINK/ULNK:建立/取消堆栈帧。这个指令用于翻译高级语言的函数调用。LINK An, #-x可将An作为函数栈指针,并SP所指向的用户栈内取得x大小的空间存储局部变量,之后SP仍将指向栈顶,而An指向栈顶+x的位置。x的值在编译时由编译器自动算出。
算数指令:ADD(加)、SUB(减)、MULU /MULS(无/有符号乘)、DIVU/DIVS(无/有符号除)、NEG (取补)、及CMP(类似于减但只会影响标志位而不改变操作数)。算数指令也多成组提供。对于ADD,还有ADDA(加地址,不会影响标志位)、ADDI(加立即数)、ADDQ(快速加,加数不大于8以便于直接放在操作码中,比x86的INC指令书写麻烦但功能更强)、ADDX(影响进位符,用于大数运算)等。
BCD码算数指令:ABCD(加)和SBCD(减)。
移位指令
逻辑移位(移位后用0补充):LSL(左移)、LSR(右移)
算数移位(移位后用原来最高/最低有效位补充):ASL(左移)、ASR(右移)
循环移位(移位后用所移动位补充):ROL(左移)、ROR(右移)
循环扩展移位(移位至CCR的X位,同时用之前的X位补充):ROXL(左移)、ROXR(右移)
位操作指令:BSET(置1)、BCLR (清0)和BTST (如果测试位在改变前为0则将CCR的Z设为1)。
多任务处理:TAS(测试并置位)。这个指令用于实现信号灯等同步机制。
流程控制:JMP(无责任跳转)、 JSR (跳转至子例程)、BSR (按相对地址跳转至子例程,多用于跳转至用户定义例程)、RTS (从子例程返回)、RTE (从异常/中断中返回)、 TRAP(自陷,即软中断)、CHK(检查地址是否越界,如是则触发异常)。
JMP指令只是纯粹跳转,不会将下一条指令地址压栈;JSR和BSR会将下一条指令压栈。
RTS将栈指针指向内容弹出给PC。
条件测试并跳转:Bcc系列指令。cc定义了所测试的条件位。常用的如:
BNE:不等于时跳转。
BEQ:等于时跳转。
BRA:无条件跳转。

来自“http://zh.wikipedia.org/wiki/%E6%91%A9%E6%89%98%E7%BD%97%E6%8B%89_68000”
2009-5-15 11:46
0
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
4
支持一下。

在学校图书馆见到过这款CPU的资料,确实很有历史了。

90年代初的时候,世嘉游戏机还是游戏机的高端产品了。当时有款游戏叫“战斧”的,很喜欢。呵呵。
2009-5-15 16:40
0
雪    币: 104
活跃值: (73)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我也好喜欢SEGA MD5游戏
好佩服当时的游戏开发人员,在受限的平台上做出性能如此优秀的游戏。SONIC系列真是帅呆了
2009-5-17 21:05
0
雪    币: 274
活跃值: (11)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
看到楼主提供的资料,想起了《浪潮之巅》中提到的复杂指令集和精简指令集之争,很有意思,推荐大家看看。
2009-5-24 10:21
0
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
7
CISC和RISC架构各有优势,目前的趋势似乎是两者都在借鉴对方的一些思想来弥补自己的不足。

比如Intel的安腾系列处理器。其中很多设计思想都是从RISC架构中吸取的。
2009-5-24 18:49
0
游客
登录 | 注册 方可回帖
返回
//