
  Another great doc for the budding assembly langage programmers.
         Part 6-10 of of the 68000 Machine Language Course
                  Brought to you by Sewer Software



ASSEMBLY LANGUAGE COURSE PART VI by Mark van den Boer

Shift and Rotate Operations

Instruction:   ASL
Syntax:        ASL #,Dn (the immediate operand always modulo 8)
               ASL Dn,Dn (the first operand always modulo 8)
               ASL <ea>
Data sizes:    byte,  word,  long  except for ASL <ea> which  only
               allows word and long as data sizes.
Condition codes affected:
               X    set to the last bit shifted out
               N    set to the most significant bit of the result
               Z    set if the result is zero, cleared otherwise
               V    set  if  the most significant bit  is  changed
                    during the operation
               C    see the X-bit





Addressing modes allowed with the ASL <ea> instruction:
Destination:
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: Perform  a shift left of the destination  operand.  This
          instruction can be used as a fast form of multiplying an
          operand  with a power of two.  On a processor  like  the
          6502  this  instruction  is the only way  to  perform  a
          multiply operation.  The lower bit of the destination is
          always set to zero.
Examples:
Instruction              Before         After
ASL.L d0,d1              d0=33333333    d0=33333333
                         d1=00000005    d1=00000028
ASL.W $4ee               $4ee=0009      $4ee=0012


Instruction:   ASR
Syntax:        ASR #,Dn (the immediate operand always modulo 8)
               ASR Dn,Dn (the first operand always modulo 8)
               ASR <ea>
Data sizes:    byte,  word,  long  except for ASR <ea> which  only
               allows word and long as data sizes.
Condition codes affected:
               X    set to the last bit shifted out
               N    set to the most significant bit of the result
               Z    set if the result is zero, cleared otherwise
               V    set  if  the most significant bit  is  changed
                    during the operation
               C    see the X-bit
Addressing modes allowed with the ASR <ea> instruction:
Destination:
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: Perform a shift right of the destination  operand.  This
          instruction  can be used as a fast form of  dividing  an
          operand  with a power of two.  On a processor  like  the
          6502  this  instruction  is the only way  to  perform  a
          divide  operation.  The upper bit (sign bit)  is  always
          repeated.
Examples:
Instruction              Before         After
ASR.L d0,d1              d0=33333333    d0=33333333
                         d1=00000005    d1=00000002
ASR.W $4ee               $4ee=8009      $4ee=c004


Instruction:   LSL
See the ASL instruction.  The LSL instruction is exactly the same.
At the moment I haven't got the machine codes for the ASL and LSL
operations  but I think that even the machine codes are the  same.
E.g.  on the 6809 both ASL and LSL exist but translate to the same
machine code.



Instruction:   LSR
Syntax:        LSR #,Dn (the immediate operand always modulo 8)
               LSR Dn,Dn (the first operand always modulo 8)
               LSR <ea>
Data sizes:    byte,  word,  long  except for LSR <ea> which  only
               allows word and long as data sizes.
Condition codes affected:
               X    set to the last bit shifted out
               N    set to the most significant bit of the result
               Z    set if the result is zero, cleared otherwise
               V    set  if  the most significant bit  is  changed
                    during the operation
               C    see the X-bit
Addressing modes allowed with the LSR <ea> instruction:
Destination:
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: Perform a shift right of the destination  operand.  This
          instruction differs from ASR in that the high order  bit
          is always cleared.
Examples:
Instruction              Before         After
LSR.L d0,d1              d0=33333333    d0=33333333
                         d1=00000005    d1=00000002
LSR.W $4ee               $4ee=0009      $4ee=0004


Instruction:   ROL
Syntax:        ROL #,Dn (the immediate operand always modulo 8)
               ROL Dn,Dn (the first operand always modulo 8)
               ROL <ea>
Data sizes:    byte, word, long
Condition codes affected:
               X    not affected
               N    set to the most significant bit of the result
               Z    set if the result is zero, cleared otherwise
               V    always cleared
               C    set to the last bit shifted out the operand

Addressing modes allowed with the ROL <ea> instruction:
Destination:
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: Perform  a  bitwise  rotate  left  of  the   destination
          operand.
Examples:
Instruction              Before         After
ROL.L d0,d1              d0=00000001    d0=00000001
                         d1=88000001    d1=10000002  (C bit set)
ROL.W $4ee               $4ee=8009      $4ee=0012






Instruction:   ROR
Syntax:        ROR #,Dn (the immediate operand always modulo 8)
               ROR Dn,Dn (the first operand always modulo 8)
               ROR <ea>
Data sizes:    byte, word, long
Condition codes affected:
               X    not affected
               N    set to the most significant bit of the result
               Z    set if the result is zero, cleared otherwise
               V    always cleared
               C    set to the last bit shifted out the operand
Addressing modes allowed with the ROR <ea> instruction:
Destination:
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: Perform  a  bitwise  rotate  right  of  the  destination
          operand.
Examples:
Instruction              Before         After
ROR.L d0,d1              d0=00000001    d0=00000001
                         d1=88000001    d1=c4000000  (C bit set)
ROR.W $4ee               $4ee=8009      $4ee=c004


Instruction:   ROXL
Syntax:        ROXL #,Dn (the immediate operand always modulo 8)
               ROXL Dn,Dn (the first operand always modulo 8)
               ROXL <ea>
Data sizes:    byte, word, long
Condition codes affected:
               X    set to the last bit shifted out the operand
               N    set to the most significant bit of the result
               Z    set if the result is zero, cleared otherwise
               V    always cleared
               C    set to the last bit shifted out the operand




Addressing modes allowed with the ROXL <ea> instruction:
Destination:
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Function: Perform  a  bitwise  rotate  left  of  the   destination
          operand.  There  is very little difference with the  ROL
          instruction.  By  the way,  it is very handy to  have  a
          wordprocessor    with   cut/paste    and    find/replace
          facilities.  All  I  did was cut out  the  complete  ROL
          instruction and replaced all ROL's by ROXL's.
Examples:
Instruction              Before         After
ROXL.L d0,d1             d0=00000001    d0=00000001
                         d1=88000001    d1=10000002
ROXL.W $4ee              $4ee=8009      $4ee=0012


Instruction:   ROXR
Syntax:        ROXR #,Dn (the immediate operand always modulo 8)
               ROXR Dn,Dn (the first operand always modulo 8)
               ROXR <ea>
Data sizes:    byte, word, long
Condition codes affected:
               X    set to the last bit shifted out the operand
               N    set to the most significant bit of the result
               Z    set if the result is zero, cleared otherwise
               V    always cleared
               C    set to the last bit shifted out the operand
Addressing modes allowed with the ROXR <ea> instruction:
Destination:
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l


Function: Perform  a  bitwise  rotate  right  of  the  destination
          operand.  There  is very little difference with the  ROR
          instruction.  By  the way,  it is very handy to  have  a
          wordprocessor    with   cut/paste    and    find/replace
          facilities.  All  I  did was cut out the  complete  ROXL
          instruction and replaced all ROXL's by ROXR's.
Examples:
Instruction              Before         After
ROXR.L d0,d1             d0=00000001    d0=00000001
                         d1=88000001    d1=10000002
ROXR.W $4ee              $4ee=8009      $4ee=0012



MC 68000 MACHINE LANGUAGE COURSE PART VII by Mark van den Boer

I would like to dedicate this part to Willeke,  who gives  Richard 
sleepless  nights and the inspiration to write even more  exciting 
issues of ST NEWS.  I only saw Willeke on photograph, but she must 
be  a fine girl.  In my opinion there are three qualities which  a 
girl  must have,  to qualify as a fine girl.  These are:  1)  like 
Queensr˜che,  2) like ST NEWS (no,  she doesn't have to like  this 
particular machine language course).
Now,  you're all anxious to know the third quality, aren't you? If 
you think you know the third one,  send your answer to ST NEWS.  A 
bottle  of  wine will be raffled among the persons  who  gave  the 
right answer.  There will be another bottle for the most  original 
answer!

Bit Manipulation instructions

Instruction:   BTST
Syntax:        BTST Dn,<ea> or BTST #,<ea>
Data sizes:    only byte when <ea> is an address.  Only long  when 
               <ea> is a data register.

Condition codes affected:
               X    not affected
               N    not affected
               Z    set if the result is zero, cleared otherwise
               V    not affected
               C    not affected
Addressing modes allowed:
Destination:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
          #         (only when source is Dn)



Function: Test a single bit of an effective address operand.  Bits 
          are  numbered  from  0  to 31,  where  0  is  the  least 
          significant bit (you could use this instruction to  test 
          if  a number is odd).  This instruction is  useful  when 
          specific  bits of an operand have to  be  checked.  E.g. 
          when reading joystick information one could test with  a 
          single  instruction whether the fire-button was  pressed 
          or not.  Compared to the 6502 and 6809 this  instruction 
          (in  fact all bit manipulation instructions) are a  step 
          forward,  since  with these older processors one had  to 
          put  the data in a register first,  then filter the  bit 
          with  an AND-operation and then the Z-bit in the  status 
          register  was at last set.  Viva el 68000!!  Since  this 
          instruction has the rather odd property of only  working 
          on  byte  and  long operands it is  important  that  you 
          remember   what  I  wrote  in  a  previous  part   about 
          specifying data sizes.





Examples:
Instruction              Before              After
BTST.B #5,$345678        $345678             $345678 contains
                         contains $78        $78
                                             Z-bit is 1
BTST.L d0,d1             d0=0                d0=0
                         d1=$12345678        d1=$12345678
                                             Z-bit is 0


Instruction:   BCLR
Syntax:        BTST Dn,<ea> or BTST #,<ea>
Data sizes:    only byte when <ea> is an address.  Only long  when 
               <ea> is a data register.
Condition codes affected:
               X    not affected
               N    not affected
               Z    set if the result is zero, cleared otherwise
               V    not affected
               C    not affected


Addressing modes allowed:
Destination:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
          #         (only when source is Dn)
Function: Bit  test and CLeaR.  First tests the bit to be  cleared 
          and  sets  the  Z-bit  accordingly,   then  clears   the 
          specified bit.






Examples:
Instruction              Before              After
BCLR.B #5,$345678        $345678             $345678 contains
                         contains $78        $58
                                             Z-bit is 1
BCLR.L d0,d1             d0=0                d0=0
                         d1=$12345678        d1=$12345678
                                             Z-bit is 0


Instruction:   BSET
Syntax:        BSET Dn,<ea> or BSET #,<ea>
Data sizes:    only byte when <ea> is an address.  Only long  when 
               <ea> is a data register.
Condition codes affected:
               X    not affected
               N    not affected
               Z    set if the result is zero, cleared otherwise
               V    not affected
               C    not affected


Addressing modes allowed:
Destination:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
          #         (only when source is Dn)
Function: Bit test and SET. First tests the bit to be set and sets 
          the Z-bit accordingly, then sets the specified bit. This 
          instruction  and  the BCLR instruction can  be  used  as 
          alternatives to the TAS-instruction.





Examples:
Instruction              Before              After
BSET.B #5,$345678        $345678             $345678 contains
                         contains $78        $78
                                             Z-bit is 1
BSET.L d0,d1             d0=0                d0=0
                         d1=$12345678        d1=$12345679
                                             Z-bit is 0


Instruction:   BCHG
Syntax:        BCHG Dn,<ea> or BCHG #,<ea>
Data sizes:    only byte when <ea> is an address.  Only long  when 
               <ea> is a data register.
Condition codes affected:
               X    not affected
               N    not affected
               Z    set if the result is zero, cleared otherwise
               V    not affected
               C    not affected


Addressing modes allowed:
Destination:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
          #         (only when source is Dn)
Function: Bit test and CHanGe.  First tests the bit to be  changed 
          and  sets  the  Z-bit  accordingly,   then  changes  the 
          specified bit.






Examples:
Instruction              Before              After
BCHG.B #5,$345678        $345678             $345678 contains
                         contains $78        $58
                                             Z-bit is 1
BCHG.L d0,d1             d0=0                d0=0
                         d1=$12345678        d1=$12345679
                                             Z-bit is 0


Binary Coded Decimal (BCD) instructions

To understand this instructionclass we must first know what a BCD-
digit is.  It is a representation of decimal digits in an array of 
bytes  (array may be of length 1 or greater).  In every  byte  the 
decimal  number  0  to 99 can be  represented.  This  is  done  as 
follows:  a  byte can be divided into two four-bit  parts,  called 
nibbles.  In every nibble,  one decimal digit is represented. This 
implicates that the binary combination 1010 can never occur in BCD 
representation,  since it isn't in the decimal range from 0 to  9. 


The BCD-representation is especially convenient when printing such 
a digit, since it doesn't take much calculation to convert it to a 
printable character.  A disadvantage of the BCD-representation  is 
that one doesn't use the full storage capacity of a byte or word.
The 68000 has three special BCD-artithmetic instructions.


Instruction:   ABCD
Syntax:        ABCD Dn,Dn or ABCD -(An),-(An)
Data sizes:    byte
Condition codes affected:
               X    set by carry out of most significant
                    BCD-nibble, cleared otherwise
               N    undefined
               Z    set if the result is zero, cleared otherwise
               V    undefined
               C    same as X-bit
Function: Add two BCD-digits.  The predecremeting addressing  mode 
          has   been  provided  for  computations  with   multiple 
          precision  BCD-numbers.   This  implies  that  the  most 
          significant  BCD-numbers  must be stored  in  the  lower 
          memory addresses.
Examples:
Instruction              Before              After
ABCD.B d0,d1             d0=$53              d0=$53
                         d1=$32              d1=$85


Instruction:   SBCD
Syntax:        SBCD Dn,Dn or SBCD -(An),-(An)
Data sizes:    byte
Condition codes affected:
               X    set by carry out of most significant
                    BCD-nibble, cleared otherwise
               N    undefined
               Z    set if the result is zero, cleared otherwise
               V    undefined
               C    same as X-bit
Function: Subtract two BCD-digits.
Examples:
Instruction              Before              After
ABCD.B d0,d1             d0=$53              d0=$53
                         d1=$32              d1=$21

Instruction:   NBCD
Syntax:        NBCD <ea>
Data sizes:    byte
Addressing modes allowed:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
Condition codes affected:
               X    set by borrow out of most significant
                    BCD-nibble, cleared otherwise
               N    undefined
               Z    set if the result is zero, cleared otherwise
               V    undefined
               C    same as X-bit



Function: Negate  a  BCD-number.  How  it functions  can  be  best 
          described with an example.  Let's negate $23.  The  NBCD 
          operation yields $77.  Now,  how did we get this result? 
          It's easy, just subtract $23 from $99 and you've got it. 
Examples:
Instruction              Before              After
NBCD.B d0                d0=$43              d0=$56


This  is  the end of part seven.  Next time I will deal  with  all 
program flow instruction, such as branches and jumps. 



MC 68000 ASSEMBLY LANGUAGE COURSE PART VIII by Mark van den Boer

Program Control Instructions

This  class of instructions enables a programmer to create  loops 
and  IF-THEN-ELSE  like  decisions.  That's  why  it's  the  most 
important group of instructions and every programmer should  have 
a  thorough knowledge of this group.  This class of  instructions 
are specifically meant to affect the program counter.

Instructions:  Bcc  (cc stands for Condition Code)
Syntax:        Bcc  <address>
Data sizes:    Byte  or word.  This implicates that  the  branch-
               instructions  can branch in an area of  32K.  When 
               using a branch with a byte offset you can put a .S 
               suffix behind the instruction e.g.  BEQ.S  .  When 
               using a branch with a word offset you can put a .W 
               suffix behind the instruction e.g.  BEQ.W  .  Most 
               assemblers  will  determine if the short  or  word 
               form is needed. Also most assemblers will optimize 
               word-branches to byte-branches whenever possible.

Condition codes affected:
               None
Function: Test  a  combination of the NZVC-flags in  the  status-
          register and conditionally perform a branch to  another 
          address. If the testing of the condition codes is true, 
          then  the  branch  will be  taken,  in  the  other  the 
          instruction  immediately following the Bcc  instruction 
          will  be executed. A total of 15 possible variations of 
          this instruction are listed below.
          BCC: where  CC stands for Carry Clear.  The  branch  is 
               taken if the C-bit is 0. This instruction is often 
               used   in  combination  with  shift   and   rotate 
               instructions.
          BCS: where CS stands for Carry Set. The branch is taken 
               if  the  C-bit  is  1.  This  instruction  is  the 
               counterpart of the BCC-instruction.
          BEQ: where EQ stand for EQual.  The branch is taken  if 
               the  Z-bit is 1.  This instruction is  often  used 
               after a TST-instruction or CMP-instruction.
          BNE: where NE stands for Not Equal. The branch is taken 
               if  the  Z-bit  is  0.  This  instruction  is  the 
               counterpart of the BNE-instruction.
          BPL: where PL stands for PLus.  The branch is taken  if 
               the  N-bit is 0.  This instruction is  often  used 
               after a TST-instruction or CMP-instruction.
          BMI: where MI stands for MInus.  The branch is taken if 
               the   N-bit  is  1.   This  instruction   is   the 
               counterpart of the BPL-instruction.
          BVC: where VC stands for oVerflow Clear.  The branch is 
               taken if the V-bit is 0. This instruction is often 
               used after an Integer Arithmetic instruction  like 
               ADD, SUB, MUL etc.
          BVS: where  VS stands for oVerflow Set.  The branch  is 
               taken if the V-bit is 1.  This instruction is  the 
               counterpart of the BVC-instruction.
          BRA: where   RA   stands  for   bRanch   Always.   This 
               instruction is often used at the end of a loop  to 
               go back to the beginning of the loop.
         Branches often used after an arithmetic operation on
         two's complement numbers.
          BGE: where GE stands for Greater or Equal.  This branch 
               is  taken  if the N and V-bits  contain  the  same 
               value.

          BGT: where GT stands for Greater Than.  This branch  is 
               taken in the following cases:
               - N is 1, V is 1, Z is 0
               - N is V is Z is 0
          BLE: where LE stands for Lower or Equal. This branch is 
               taken in the following cases:
               - Z is 1
               - N and V-bits contain different values
          BLT: where  LT  stands for Less Than.  This  branch  is 
               taken  if  the  N  and  V-bits  contain  different 
               values.
         Brances often used after an arithmetic operation on
         unsigned numbers.
          BHI: where HI stands for HIgher.  This branch is  taken 
               if the N and V-bits contain the same value.
          BLS: where LS stands for Lower or Same.  This branch is 
               taken  if  the  C  and  Z-bits  contain  different 
               values.
Example:
          This  shows  a piece of a C-program and  an  equivalent 
          piece  of  a PASCAL-program which are  translated  into 
          assembler. (variabele is signed)
          C:
               if (variable == 1 || variable > 4) variable = 5;
               else var *= 3;
          PASCAL:
               if (variable == 1) or (variable > 4)
               then variable := 5
               else variable := variable * 3

          * Most assemblers will optimize the branch-instructions
          * to the short forms
                 CMP.W   #1,variable
                 BEQ     L10000
                 CMP.W   #4,variable
                 BLE     L2
          L10000:
                 MOVE.W  #5,variable
                 BRA     L3
          L2:
                 MOVE.W  variable,R0
                 MULS    #3,R0
                 MOVE.W  R0,variable
          L3:
Instructions:  DBcc  (cc stands for Condition Code)
Syntax:        DBcc  Dn,<address>
Data sizes:    byte  or word.  This implicates that  the  branch-
               instructions can branch in an area of 32K.  Dn  is 
               considered to contain a word.
Condition codes affected:
               None
Function:
          The  group of Decrement and Branch (DBcc)  instructions 
          provide  an efficient way of creating loops.  They  are 
          nearly  always placed at the end of a loop.  First  the 
          condition   is  tested,   then  the   dataregister   is 
          decremented.  The  branch  is taken  in  the  following 
          cases:
          - Dn is -1;
          - The condition cc in DBcc is satisfied.
          There  are 16 possible variations of this  instruction. 
          They  all are nearly the same as the  Bcc-instructions, 
          with two exceptions. These are:
          DBF or DBRA:
               This  loop can only be terminated by  count  since 
               the other condition can never be satisfied.
          DBT: Only performs a decrement on the dataregister  and 
               never branches.  To me this seems a pretty useless 
               instruction,  which is only there to make the DBcc 
               series logically complete.
Example:
          This  piece of code is an efficient  implementation  of 
          the strcpy-function of the C-language.  A0 contains the 
          address  of  the  source string  and  A1  contains  the 
          address  of the destination string.  In C the end of  a 
          string is marked by a byte containing 0.
                 MOVE.W  #$ffff,D0
          LOOP:  MOVE.B  (A0)+,(A1)+
                 DBEQ    D0,LOOP
          This  piece of code can easily be transformed into  the 
          strncpy-function  by  loading D0 with  the  appropriate 
          value.


Instructions:  Scc  (cc stands for Condition Code)
Syntax:        Scc  <address>
Data sizes:    byte.

Condition codes affected:
               None
Function: Sets a byte to $ff if the condition codes satisfie.  If 
          the  condition is not satisfied the byte is set  to  0. 
          This  group of 16 instructions is rarely  used.  Nearly 
          all forms are the same as the DBcc group except for the 
          following two instructions:
          SF:  the same as a CLR.B instruction
          ST:  the same as a MOVE.B #$ff, <address>
Example:
          Be inventive, invent one yourself!


Instruction:   BSR, JSR
Syntax:        BSR  <address>
               JSR  <address>
Data sizes:    none
Condition codes affected:
               none



Addressing modes allowed (only for JSR):
Destination:
          (An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
Function: The  BSR  (Branch  to  SubRoutine)  and  JSR  (Jump  to 
          SubRoutine)   instructions   are   used   for   calling 
          subroutines.  BSR  can branch in a range  of  32K.  JSR 
          should  be  used when a jump out of the  32K  range  is 
          needed.   Some   assemblers  optimize  JSR   into   BSR 
          instructions  whenever  possible,  since  BSR  is  more 
          efficient   than   JSR.   When  executing   a   BSR/JSR 
          instruction,  the  68000 first pushes the PC  (program-
          counter) on the stack and then load the PC with the new 
          address. See below for the RTS (ReTurn from Subroutine) 
          instruction.


Instruction:   RTS
Syntax:        RTS
Data sizes:    none
Condition codes affected:
               none
Function: Counterpart  of BSR/JSR instructions.  Reloads  the  PC 
          with  the value on top of the stack.  This  value  will 
          nearly  always have been put on top of the stack  by  a 
          BSR/JSR instruction.
Example:  * the strcpy function discussed before
          STRCPY:
                 MOVE.W  #$FFFF,D0
          LOOP:  MOVE.W  (A0)+,(A1)+
                 DBEQ    D0, LOOP
                 RTS
          * some other code
          BEGIN:
                 MOVE.L  #SOURCE,A0
                 MOVE.L  #DEST,A1
                 JSR     STRCPY
                 RTS

          * the strings are put in a data area
          .DATA
          * 80 bytes for every string
          SOURCE .DS.B   80
          DEST   .DS.B   80
          * .DS.B means Define Storage Byte
          * so 80 bytes are define as storage for each string


Instruction:   JMP
Syntax:        JMP  <ea>
Data sizes:    none
Condition codes affected:
               none








Addressing modes allowed:
Destination:
          (An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
Function: Transfer program control to another address.  The PC is 
          loaded  with the specified address.  In fact this is  a 
          variant  of  the MOVE instruction.  In  this  case  the 
          destination register is inherently defined,  namely the 
          PC-register.  Therefore we could translate JMP <ea>  to 
          MOVE.L <ea>,PC .

Instruction:   RTR
Syntax:        RTR
Data sizes:    none
Condition codes affected:
               none

Function: ReTurn    and   Restore.    Counterpart   of    BSR/JSR 
          instructions.  Reloads the PC with the value on top  of 
          the stack.  This value will nearly always have been put 
          on top of the stack by a BSR/JSR instruction.  The only 
          difference  with the RTS is that with this  instruction 
          also  the CCR is reloaded.  This instruction is  rarely 
          used  but  comes  in  handy when  one  doesn't  want  a 
          subroutine to influence the condition codes. Before the 
          JSR instruction you should use the instruction:
          MOVE.B CCR,-(A7)
          which pushes the CCR on the stack

Next time:  The last part of the instruction set.  These are  the 
instructions  which can only be executed when supervisor-mode  is 
active.



ASSEMBLY LANGUAGE COURS PART IX by Mark van den Boer

System Control instructions

In this part of the course the last group of instructions will be 
explained.  This group of instructions deals with the supervisor-
mode  and are therefore sometimes referred to as  system  control 
instructions.  To  remind  you:  the  S-bit  in  the  SR  (status 
register)  of  the  68000  determines whether  the  68000  is  in 
supervisor-mode or not.  Many of these instructions deal with  so 
called  exceptions.  Exception is another word for interrupt  and 
these are used to force program control immediately to a specific 
routint exception handler routine.  Exceptions are used to detect 
situations  that  are  urgent and need to  be  handled  directly. 
Therefore  every  exception has a vector  assigned  to  it.  This 
vector is a pointer to a routine which performs some action which 
should  be  taken when such an exception  occurs.  The  exception 
vectors are located in the first 256 longwords of memory.




Instruction:   CHK
Syntax:        CHK <ea>,Dn
Data sizes:    word
Condition codes affected:
               X    not affected
               N    Set if Dn is less than zero,  cleared if <ea> 
                    less than Dn, in all other cases undefined
               Z
               V
               C    always undefined












Addressing modes allowed:
Source:
          Dn
          (An)
          (An)+
          -(An)
          w(An)
          b(An,Rn)
          w
          l
          w(PC)
          b(PC,Rn)
          #
Destination:
          Dn







Function: Compares the contents of the effective address  operand 
          with  the data-register.  If the data register is  less 
          than zero (the data register is always considered to be 
          a  signed word) or greater than the contents  of  <ea>, 
          then   an  exception  occurs.   The  pointer  to   this 
          exception-routine  is  located  at  address  $18.  This 
          instruction  is  used to check if a  data  register  is 
          within  a  range.   It  is  often  used  by  high-level 
          languages   such  as  PASCAL  to  perform   array-bound 
          checking.
Examples:
Instruction              Before              After
CHK #50,D0               D0=45               D0=45
                         No exception occured, if D0 had been 51
                         or greater then an exception would have
                         occured.


Instruction:   MOVE USP       (privileged instruction)
Syntax:        MOVE USP,An    or   MOVE An,USP
Data sizes:    long

Condition codes affected:
               X
               N
               Z
               V
               C    not affected
Addressing modes allowed:
     See syntax
Function: As  you all should know,  the 68000 has in fact two  A7 
          registers.  One A7 register is used when in supervisor-
          mode,  the  other  when in usermode (this  is:  not  in 
          supervisor-mode.   It  is  sometimes  desirable  for  a 
          program  which is executing in supervisor mode to  know 
          the value of the usermode A7-register. This instruction 
          provides  a  way to obtain and change the value  of  A7 
          usermode-register.
Example:
Instruction              Before              After
MOVE USP,A6              A7user=$12345678    A7user=$12345678
                         A6    =$00000000    A6    =$12345678
                         A7sup =$87654321    A7sup =$87654321

Instruction:   RESET
Syntax:        RESET          (privileged instruction)
Data sizes:    none
Condition codes affected:
               X
               N
               Z
               V
               C    not affected
Function: Reset all external devices. A device can be a chip like 
          the 6850.


Instruction:   RTE            (privileged instruction)
Syntax:        RTE
Data sizes:    none
Condition codes affected:
               none




Function: Every exception is terminated by this  instruction.  It 
          can be compared to RTS. The only difference is that RTE 
          will  restore  the  SR  in  addition.   Note  that   an 
          exception-routine   has  the  responsibility  to   save 
          registers if this is important.


Instruction:   STOP           (privileged instruction)
Syntax:        STOP #
Data sizes:    word
Condition codes affected:
          All set as a direct result of the operand
Addressing modes allowed:
Source:
          #
Function: Stop execution of a program until an exception  occurs. 
          The  operand  stored  in the SR.  Note  that  with  the 
          operand  a minimum interrupt level can  be  determined. 
          With  this  instruction it is possible to  wait  for  a 
          videochip interrupt to occur.


Example:
          STOP #%0010011000011111
          Wait  for  an exception with a priority of 6  or  7  to 
          occur and set the XNZVC-bits.


Instruction:   TRAP
Syntax:        TRAP #
Data sizes:    # must be >=0 and <=15
Condition codes affected:
               X
               N
               Z
               V
               C    not affected







Function: This  instruction generates an exception.  The  operand 
          indicates  an  exception number.  The vectors  for  the 
          exceptions  are located at addresses $80 to  $BC.  This 
          instruction  is  mainly  used to  allow  programs  that 
          execute in user-mode to call supervisor-mode  routines. 
          This  way  a  user can be given a  number  of  specific 
          functions. In the ST trap vectors 2, 14 and 15 are used 
          for GEM,  BIOS and XBIOS functions.  In the case of the 
          ST  the TRAP-instructions is preceded  by  instructions 
          that  put  function numbers and  parameters  for  these 
          functions  on  the stack.  This way it is  possible  to 
          assign groups of functions to one trap-vector.
          Note  that  when  calling  a  TRAP  in  user-mode   the 
          stackpointers  change (supervisor-mode  and  user-mode, 
          remember??). Thus, the MOVE USP instruction can be used 
          to retrieve parameters that had been put on the stack.


Instruction:   TRAPV
Syntax:        TRAPV
Data sizes:    none

Condition codes affected:
               none
Function: When  the  V-bit  is  set  an  exception  occurs.   The 
          exception vector is located at address $1C. When the V-
          bit is clear nothing happens.  This instruction can  be 
          used by high-level languages to inform the user that an 
          overflow error has occured.



MC 68000 ASSEMBLY LANGUAGE COURSE PART X by Mark van den Boer

Now  all instructions of the 68000 have been explained it's  time 
to  bring  this knowledge into practice.  This last part  of  the 
course  will  deal  with the subject  of  translating  high-level 
constructs to the equivalent assembler constructs. The C program-
ming  language will be used as the high-level language which  has 
to  be translated to assembler.  A note to those of you  who  are 
more familiar with Pascal or BASIC:  litte imagination is needed 
to deduct the similar constructs in Pascal and BASIC.
What now follows is a C-program which containing several commonly 
used data- and control structures.  The examples show you how  to 
translate these structures into assembler.
There  should  also be a file called M68000.DOC on your  ST  NEWS
disk.  This  file contains a quick-reference card containing  all 
instructions  and allowed addressing modes.  This reference  card 
has been made by Trustware,  Inc.  (an unregistered trademark  of 
Victor Langeveld).  I am very grateful to Victor for allowing  me 
to  include  this card,  since it's a rather tedious job  to  put 
together such a card.  One thing's for sure:  this card is one of 
the  better of its kind and it's the most compact reference  card 
for the 68000 I've ever seen.
/*
        A function. (Called a procedure or function in Pascal
        and a subroutine in BASIC)
        Note how parameters are passed in the assembly language
        translation.
        Als pay attention to how local variables are stored.
*/
int function (number, pointer)
int     number;
char    *pointer;
{
        register int    i, j;
        char    *c;

        i = number - 1;
        c = pointer;
        c = "new Queensryche album: Operation Mindcrime";
        /* Note how a string is stored */
        return i;          /* Note how a value is returned */
}


.text
function:
* offset of number = 8
* offset of pointer = 10
        LINK    A6,#-4
* save registers
        MOVEM.L D6-D7,-(sp)     * sp = A7
* i in D7
* j in D6
* offset of c = -4
* i = number - 1
        MOVE.W  8(A6),D7
        SUB.W   #1,D7
* c = pointer
        MOVE.L  10(A6),-4(A6)
* c = "new Queensryche album: Operation Mindcrime"
.data





L2:
        .dc.b 'new Queensryche album: Operation Mindcrime',0
        MOVE.L  #L2,-4(A6)
* D0 is used for resulting values from functions
* return i; D0 is always used for the result of a function
        MOVE.W  D7,D0
* restore registers
        MOVEM.L (sp)+,D6-D7
        UNLK    A6
* }
        RTS

* global variables
.bss
* int     i;
i:      .ds.w   1
* char    character
character:      .ds.b   1
* int     *i_pointer
i_pointer:      .ds.l   1


* int     i_array[10][5]
i_array:        .ds.w   10*5
* one struct is in fact 3 bytes long, but for every structure
* 4 bytes are reserved. This is because the 68000 can only
* address words at even addresses.
* struct { /* this is the equivalent of a record in PASCAL */
*         int     i;
*         char    c;
* } structure[5];
structure:      .ds.b   4*5


main()
{
        /* assignment of a constant to a variable */
        i = 9;

        /* assignment of a constant to a variable */
        character = 'c';

        /* assignment of a constant to a variable */
        i_pointer = &i;
        /* watch how indexing of array is done */
        /* integer is 2 bytes, so the address of
           array-element [3][4] is:
           (3 * 5 (the length of i_array[3]) + 4)
           * 2 (size of an integer) = 38.
           So the integer should be stored at i_array + 38.
        */
        i_array[3][4] = *i_pointer;

        /* Now the distance in bytes from the beginning of the
           array must be computed during program execution,
           in contrary to the previous example.
        */
        i_array[i][i - 1] = 2;

        /* Assignments to arrays of structures */
        structure[1].i = 3;
        structure[i].c = character;

        /* expression evaluation and assignment */
        i = i_array[0][0] * i_array[0][1] +
            i_array[0][2] / i_array[0][3];
        /* conditional statement */
        if (i < i_array[i][i]) i = 1;
        else i = 2;

        /* while loop */
        while (i <= 10) i++;
        /* continue and break statements */
        while (i++ <= 10) {
                if (i != 4) continue;
                else break;
        }

        /* for loop */
        for (i = 4; i >= 0; i--) i_array[i][i] = i;

        /* do loop */
        do i++; while (i < 10 && i != 5);

        /* switch statement; watch the application of a
           jump-table. Pay special attention to how 'case 4'
           which must 'default' is solved.

        */
        switch (i) {
        case 0:
                i = 0;
                break;
        case 1:
                i = 5;
                break;
        case 2:
        case 3:
                i = 7;
                break;
        case 5:
                i = 1;
                break;
        default:
                i = 2;
                break;
        }



        /* switch statement;
           watch how 'case 999' has destroyed the
           jumptable-optimization.
        */
        switch (i) {
        case 0:
                i = 0;
                break;
        case 1:
                i = 5;
                break;
        case 2:
        case 3:
                i = 7;
                break;
        case 5:
                i = 1;
                break;
        case 999:
                /* This case should be tested seperately so
                   the assembler code can be more efficient.

                */
                i = 100;
                break;
        default:
                i = 2;
                break;
        }

        /* manipulating bits */
        i = i & 0x2345;
        i = i | 0x2345;
        i = i ^ 0x2345;
        i = ~i;
        i <<= i;

        /* using the result of a function */
        i = function(5, &character);

}

.text

main:
* Reserve 4 bytes. This way, when the first parameter for a
* function is pushed onto the stack, no pre-decrementing of sp
* has to be done. This 'trick' is used by the DRI-C-compiler.
        LINK    A6,#-4
* i = 9
        MOVE.W  #9,i
* character = 'c'
        MOVE.B  #'c,character
* i_pointer = &i
        MOVE.L  #i,i_pointer
* i_array[3][4] = *i_pointer
        MOVE.L  i_pointer,A0
        MOVE.W  (A0),38+i_array
* i_array[i][i - 1] = 2
        MOVE.W  i,D0     * compute byte offset from first element
        MULS    #10,D0
        MOVE.W  i,D1
        SUB.W   #1,D1
        ASL.W   #1,D1   * multiply by 2 because an int is 2 bytes
        EXT.L   D1
        ADD.L   D1,D0
        ADD.L   #i_array,D0
        MOVE.L  D0,A0   * move computed address to address-reg
        MOVE.W  #2,(A0)
* structure[1].i = 3
        MOVE.W  #3,4+structure
* structure[i].c = character
        MOVE.W  i,A0
        ADD.L   A0,A0
        ADD.L   A0,A0
* Two ADD operations are faster than a MUL and a MOVE
        ADD.L   #structure,A0
        MOVE.B  character,2(A0)
* i = i_array[0][0] * i_array[0][1] +
*     i_array[0][2] / i_array[0][3];
        MOVE.W  i_array,D0
        MULS    2+i_array,D0
        MOVE.W  4+i_array,D1
        EXT.L   D1
        DIVS    6+i_array,D1
        ADD.W   D1,D0
        MOVE.W  D0,i
* if (i < i_array[i][i]) i = 1;
* else i = 2;
        MOVE.W  i,D0
        MULS    #10,D0
        MOVE.W  i,D1
        ASL.W   #1,D1
        EXT.L   D1
        ADD.L   D1,D0
        MOVE.L  D0,A0
        MOVE.L  #i_array,A1
        MOVE.W  0(A0,A1.L),D0
        CMP     i,D0
        BLE     L4
* i = 1
        MOVE.W  #1,i
        BRA     L5
L4:
* i = 2
        MOVE.W  #2,i
L5:
        BRA     L8


* while (i <= 10) i++;
* This loop has been optimized:
* one BRA instruction was saved by putting the test after the
* do-part. The label L5:    BRA L8    takes care that the while
* condition is executed first at the beginning of the loop
L7:
        ADD.W   #1,i
L8:
        CMP.W   #10,i
        BLE     L7
* while (i++ <= 10) {
*   if (i != 4) continue;
*   else break;
* }
L6:
        BRA     L11
L10:
        CMP.W   #4,i
        BNE     L11
        BRA     L9


L11:
        CMP     #10,i
        MOVE.W  SR,D0   * save condition codes
        ADD.W   #1,i
        MOVE    D0,CCR  * and restore
        BLE     L10
* for (i = 4; i >= 0; i--) i_array[i][i] = i
L9:
        MOVE.W  #4,i
        BRA     L14
L15:
        MOVE.W  i,D0
        MULS    #10,D0
        MOVE.W  i,D1
        ASL.W   #1,D1
        EXT.L   D1
        ADD.L   D1,D0
        ADD.L   #i_array,D0
        MOVE.L  D0,A0
        MOVE.W  i,(A0)
L13:
        SUB.W   #1,i
L14:
        TST     i
        BGE     L15
L12:
* do i++; while (i < 10 && i != 5);
L18:
        ADD.W   #1,i
L17:
        CMP.W   #10,i
        BGE     L10000
        CMP.W   #5,i
        BNE     L18
L10000:
* switch (i) {
* case 0:
*        i = 0;
*        break;
* case 1:
*        i = 5;
*        break;


* case 2:
* case 3:
*        i = 7;
*        break;
* case 5:
*        i = 1;
*        break;
* default:
*        i = 2;
*        break;
* }
L16:
        MOVE.W  i,D0
        BRA     L20
L21:
        CLR.W   i
        BRA     L19
L22:
        MOVE.W  #5,i
        BRA     L19


L23:
L24:
        MOVE.W  #7,i
        BRA     L19
L25:
        MOVE.W  #1,i
        BRA     L19
L26:
        MOVE.W  #2,i
        BRA     L19
L20:
* Test if i is in case-range
* if not goto default
* if in range compute address to jump to
        CMP.W   #5,D0
        BHI     L26
        ASL.W   #2,D0
        MOVE.W  D0,A0
        ADD.L   #L27,A0
        MOVE.L  (A0),A0
        JMP     (A0)
.data
L27:
* jumptable
.dc.l L21
.dc.l L22
.dc.l L23
.dc.l L24
.dc.l L26
.dc.l L25
.text
L19:
* switch (i) {
* case 0:
*         i = 0;
*         break;
* case 1:
*         i = 5;
*         break;
* case 2:
* case 3:
*         i = 7;
*         break;

* case 5:
*         i = 1;
*         break;
* case 999:
*         /* This case should be tested seperately so
*            the assembler code can be more efficient.
*         */
*         i = 100;
*         break;
* default:
*         i = 2;
*         break;
* }
        MOVE.W  i,D0
        BRA     L29
L30:
        CLR.W   i
        BRA     L28
L31:
        MOVE.W  #5,i
        BRA     L28

L32:
L33:
        MOVE.W  #7,i
        BRA     L28
L34:
        MOVE.W  #1,i
        BRA     L28
L35:
        MOVE.W  #100,i
        BRA     L28
L36:
        MOVE.W  #2,i
        BRA     L28
        BRA     L28
L29:
        EXT.L   D0
        MOVE.L  #L37,A0
        MOVE.W  #6,D1




L38:
        CMP.L   (A0)+,D0
        DBEQ    D1,L38
        MOVE.L  24(A0),A0
        JMP     (A0)
.data
L37:
* table of case values
.dc.l 0
.dc.l 1
.dc.l 2
.dc.l 3
.dc.l 5
.dc.l 999
.dc.l 0
* jump table
.dc.l L30
.dc.l L31
.dc.l L32
.dc.l L33
.dc.l L34
.dc.l L35
.dc.l L36
.text
L28:
* i = i & 0x2345
        ANDI.W  #$2345,i
* i = i | 0x2345
        ORI.W   #$2345,i
* i = i ^ 0x2345
        EORI.W  #$2345,i
* i = ~i
        NOT.W   i
* i <<= i
        MOVE.W  i,D1
        MOVE.W  D1,D0
        ASL.W   D1,D0
        MOVE.W  D0,i
* i = function (5, &character)
        MOVE.W  #51,(sp)
        MOVE.L  #character,-(sp)
        ADDQ.L  #4,sp
        MOVE.W  D0,i

L3:
        UNLK    A6
        RTS


Hope you had much fun with this course and that you learnt a lot!