M68K Complete Documentation
Addressing Modes
In the documentation, wherever there is (An), this addressing mode is valid too
Condition Codes
For example the tst, cmp instructions will set the condition codes that represent the result of the comparison of the operands.
The following are all the condition codes available:
Condition codes flags
X is the extend flag, it is set when the result of an operation is too large to fit in the destination register.
N is the negative flag, it is set when the result of an operation is negative.
Z is the zero flag, it is set when the result of an operation is zero.
V is the overflow flag, in arithmetical operations, it is set if it caused the result to overflow.
C is the carry flag, when an operation causes a carry, like an addition or a shift, it is set to the value of the carry.
Shift Directions
Directives
Defines constants, following the directive there can be a list of constants separated by commas, the size of each constant depends on the selected size. If no size is selected, the size is determined by the value of the constant. If the constant is a string, it will be stored as a sequence of bytes, if it is a number, it will be stored as a sequence of words
Defines a space in memory of N elements, the size of each element depends on the specified size, the content of the space is undefined
Defines a space in memory of N elements, the size of each element depends on the specified size, the content of the space is initialized to the second operand
Sets the current position in memory for the following instructions
Defines a constant that will be replaced by the value when the program is assembled
Assembler Features
Instructions
add
(b, w, l) {w}Adds the value of the first operand to second operand. If the second operand is an address register, the ADDA instruction is used instead.
adda
(l, w) {w}Adds the value of the first operand to second operand. It does not change the SR. When using word size, the first operand is sign extended to long and the second is read and written as a long.
addi
(b, w, l) {w}Adds the immediate value to the second operand
addq
(b, w, l) {w}Adds the value of the first operand to second operand. The first operand value must be between 1 and 8. If the destination is a address register, it is always treated as a long, and the condition codes are not affected.
and
(b, w, l) {w}Performs a logical AND between the first and second operand, stores the result in the second operand
andi
(b, w, l) {w}Performs a logical AND between the first immediate value and second operand, stores the result in the second operand
asd
(b, w, l) {w}Shifts the bits of the second operand to the {direction} as many times as the value of the first operand, depending on the specified size. The new bits are filled with the sign bit. Defaults to word. Note: ASL sets the overflow flag if the MSB changes during the shift, while ASR always clears it
bcc
Branches to the specified address if {condition code}
bchg
Inverts the bit of the second operand at the position of the value of the first operand
bclr
Clears the bit of the second operand at the position of the value of the first operand
bra
Branches to the specified address unconditionally
bset
Sets to 1 the bit of the second operand at the position of the value of the first operand
bsr
Branches to the specified address and stores the return address in the stack
btst
Tests the bit of the second operand at the position of the value of the first operand, it changes the Z (zero) flag, the destination operand is not modified
clr
(b, w, l) {w}Sets to 0 all the bits of the destination operand, how many bits are set to 0 depends on the specified size, defaults to long
cmp
(b, w, l) {w}Compares the second operand with the first operand, it sets the flags accordingly which will be used by the branching instructions. Works by subtracting the first operand from the second operand and setting the flags. If the second operand is an address register, the CMPA instruction is used instead.
cmpa
(l, w) {w}Compares the second operand with the first operand, it sets the flags accordingly which will be used by the branching instructions. When using word size, the first operand is sign extended to long and the second is read and written as a long.
cmpi
(b, w, l) {w}Compares the second operand with the first operand, it sets the flags accordingly which will be used by the branching instructions.
cmpm
(b, w, l) {w}Compares two memory regions, only valid operand is the post increment, it sets the flags accordingly which will be used by the branchin instructions.
dbcc
Decrements the first operand by 1 and branches to the specified address if {condition code} is false and the first operand is not -1. dbra is the same as dbf (will decrement untill it reaches -1). It reads the operand as a word, so it can run at maximum 64k times
dbra
Decrements the first operand by 1 and branches to the specified address if the first operand is not -1. dbcc is the same as dbf (will decrement untill it reaches -1)
divs
Divides (signed) the value of the second operand by the value of the first operand (op2 / op1). The quotient is stored in the first 16 bits of the destination register and the remainder is stored in the last 16 bits of the destination register. The first operand is read as a word, the second as a long
divu
Divides (unsigned) the value of the second operand by the value of the first operand (op2 / op1). The quotient is stored in the first 16 bits of the destination register and the remainder is stored in the last 16 bits of the destination register. The first operand is read as a word, the second as a long
eor
(b, w, l) {w}Performs a logical XOR between the first and second operand, stores the result in the second operand
eori
(b, w, l) {w}Performs a logical XOR between the first immediate value and second operand, stores the result in the second operand
exg
Exchanges the values of the two operands, only works in 32 bits
ext
(l, w) {w}Extends the sign of the operand, depending on the specified size. If the part to extend is negative, it will be filled with 1s, otherwise it will be filled with 0s. Defaults to word
jmp
Jumps to the specified address unconditionally
jsr
Jumps to the specified address, like the "lea" instruction, when resolving the address, it does not read the memory, so "jsr 4(a0)" will jump to the value of "a0 + 4", the address is loaded and stores the return address in the stack
lea
Loads the address of the first operand into the second operand, when using indirect addressing, the value is not read, only the address is loaded. For example "lea 4(a0), a0" will load a0 + 4 in a1
link
Pushes to the stack the long content of the address register, sets the address register to the current stack pointer and then decrements the stack pointer by the specified amount
lsd
(b, w, l) {w}Shifts the bits of the second operand to the {direction} as many times as the value of the first operand, depending on the specified size. The new bits are filled with 0s. Defaults to word
move
(b, w, l) {w}Moves the value from the first operand to second operand. If the second operand is an address register, the MOVEA instruction is used instead.
movea
(l, w) {w}Moves the value from the first operand to second operand. If the size is word, it is sign extended to long. It does not change the SR. When using word size, the first operand is sign extended to long and the second is written as a long.
movem
(l, w) {w}Move many, useful when you want to save a bunch of registers, for example to save their value when branching to a function it moves a list of registers to memory, or memory to a list of registers. The first operand is the list of registers, the second operand is the memory region. If you define the registers as the first operand, then it will save the registers to memory, if the first operand is the memory, then it will load the registers from memory. You can write the list of registers by separating them with a "/", and the range between registers by using a dash. ex: a3-a5/d0-d2 will select d0, d1, d2, a3, a4, a5. The order of the register will be converted to first data, then address registers, from 0 to 7. When using the pre-decrement operand, the order of the registers will be reversed, going from a7 to a0, and d7 to d0.
moveq
Moves the value from the first operand to second operand. The first operand is read as a byte so only values between -127 and 127.
muls
Multiplies the value of the first operand by the second operand. The result is stored in the second operand. The first operand is read as a word, the second as a long
mulu
Multiplies (unsigned) the value of the first operand by the second operand. The result is stored in the second operand. The first operand is read as a word, the second as a long
neg
(b, w, l) {w}Flips the sign of the operand, depending on the specified size, defaults to word
nop
nop
not
(b, w, l) {w}Inverts the bits of the operand depending on the specified size
or
(b, w, l) {w}Performs a logical OR between the first and second operand, stores the result in the second operand
ori
(b, w, l) {w}Performs a logical OR between the first immediate value and second operand, stores the result in the second operand
pea
Same as lea, but it pushes the address to the stack
rod
(b, w, l) {w}Rotates the bits of the second operand to the {direction} as many times as the value of the first operand, depending on the specified size. Defaults to word
rts
Returns from a subroutine, pops the return address from the stack and jumps to it
scc
Sets the first byte of the destination operand to $FF (-1) if flags {condition code} is true, otherwise it sets it to 0
sub
(b, w, l) {w}Subtracts the value of the first operand from second operand and stores in the second. If the second operand is an address register, the SUBA instruction is used instead.
suba
(l, w) {w}Subtracts the value of the first operand from second operand and stores in the second. It does not change the SR. When using word size, the first operand is sign extended to long and the second is read and written as a long.
subi
(b, w, l) {w}Subtracts the immediate value to the second operand
subq
(b, w, l) {w}Subtracts the value of the first operand from second operand and stores in the second. The first operand value must be between 1 and 8. If the destination is a address register, it is always treated as a long, and the condition codes are not affected.
swap
Swaps the two word of the register, you can see the register as [a,b] after the swap it will be [b,a]
trap
Executes a trap, the value of the operand is used as the trap number, only #15 is supported. The register d0 will be used as the trap type which are:
| Opcode | Description |
|---|---|
| 0 | Print string pointed by a1 with length read in d1.w, null terminated with max of 255, then prints a new line. |
| 1 | Print string pointed by a1 with length read in d1.w. |
| 2 | Read string from keyboard, writes the string at address of a1 and overrides the value of d1 with the length of the string. |
| 3 | Print signed number at d1. |
| 4 | Read number, writes to d1. |
| 5 | Read character, writes to d1. |
| 6 | Print character at d1. |
| 8 | Get time, writes to d1. |
| 9 | Terminate. |
| 13 | Prints null terminated string pointed by a1 then prints new line, errors if string is longer than 16kb, to prevent infinite loops. |
| 14 | Prints null terminated string pointed by a1, errors if string is longer than 16kb, to prevent infinite loops. |
| 15 | Prints unsigned number at d1 in base (from 2 to 36) specified in d2.b |
| 23 | Delays the execution of the simulator by milliseconds of the value in d1. |
tst
(b, w, l) {w}Compares the operand with 0
unlk
Sets the SP to the address register, then Pops a long value from the stack and stores the result in the address register