Skip to content

Latest commit

 

History

History
639 lines (439 loc) · 18.4 KB

m68k.md

File metadata and controls

639 lines (439 loc) · 18.4 KB

Instructions:

add.(b, w, l) {w}
    Op 1: Dn/An/(An)/Im/ea
    Op 2: Dn/(An)/An/ea

    Adds the value of the first operand to second operand. If the second
    operand is an address register, the ADDA instruction is used instead.

    Example: add.l (a4, d3), d1

adda.(l, w) {w}
    Op 1: Dn/An/(An)/Im/ea
    Op 2: An

    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.

    Example: adda.l d0, a0

addi.(b, w, l) {w}
    Op 1: Im
    Op 2: Dn/(An)/ea

    Adds the immediate value to the second operand

    Example: addi.w #4, d1

addq.(b, w, l) {w}
    Op 1: Im
    Op 2: Dn/(An)/An/ea

    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.

    Example: addq.w #4, d1

and.(b, w, l) {w}
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    Performs a logical AND between the first and second operand, stores the
    result in the second operand

    Example: and.l d0, d1

andi.(b, w, l) {w}
    Op 1: Im
    Op 2: Dn/(An)/ea

    Performs a logical AND between the first immediate value and second
    operand, stores the result in the second operand

    Example: andi.l #$FF, (a0)

asd.(b, w, l) {w}
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    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

    Example: `as<d> d0, d3` Where d is either (l)eft or (r)ight

bcc
    Op 1: ea

    Branches to the specified address if {condition code}

    Example: `b<cc> label` Where cc is one of the condition codes

    Condition Codes:
        hi: Unsigned higher
        ls: Unsigned lower or same
        cc: Carry clear
        cs: Carry set
        ne: Not equal
        eq: Equal
        vc: Overflow clear
        vs: Overflow set
        pl: Plus
        mi: Minus
        ge: Greater or equal
        lt: Less than
        gt: Greater than
        le: Less than or equal
        hs: Unsigned higher or same
        lo: Unsigned lower

bchg
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    Inverts the bit of the second operand at the position of the value of
    the first operand

    Example: bchg #%101, d3

bclr
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    Clears the bit of the second operand at the position of the value of the
    first operand

    Example: bclr d2, d7

bra
    Op 1: ea

    Branches to the specified address unconditionally

    Example: bra $2000

bset
    Op 1: Dn/(An)/Im/ea
    Op 2:: Dn/(An)/ea

    Sets to 1 the bit of the second operand at the position of the value of
    the first operand

    Example: bset #1, d1

bsr
    Op 1: ea

    Branches to the specified address and stores the return address in the
    stack

    Example: bsr label

btst
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    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

    Example: btst #4, d0

clr.(b, w, l) {w}
    Op 1: Dn/(An)/ea

    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

    Example: clr.b d0

cmp.(b, w, l) {w}
    Op 1: Dn/An/(An)/Im/ea
    Op 2: Dn/An

    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.

    Example: cmp.l -(sp), d0

cmpa.(l, w) {w}
    Op 1: Dn/An/(An)/Im/ea
    Op 2: An

    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.

    Example: cmpa.l $1000, a0

cmpi.(b, w, l) {w}
    Op 1: Im
    Op 2: Dn/(An)/An/ea

    Compares the second operand with the first operand, it sets the flags
    accordingly which will be used by the branching instructions.

    Example: cmpi.w #10, d3

cmpm.(b, w, l) {w}
    Op 1: (An)
    Op 2: (An)

    Compares two memory regions, only valid operand is the post increment,
    it sets the flags accordingly which will be used by the branchin
    instructions.

    Example: cmpm.b (a0)+, (a1)+

dbcc
    Op 1: Dn
    Op 2: ea

    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

    Example: `db<cc> d0, label` Where cc is one of the condition codes

dbra
    Op 1: Dn
    Op 2: ea

    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)

    Example: dbra d0, label

divs
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn

    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

    Example: divs #2, d1

divu
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn

    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

    Example: divu #@4, d1

eor.(b, w, l) {w}

    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    Performs a logical XOR between the first and second operand, stores the
    result in the second operand

    Example: eor.l d0, d1

eori.(b, w, l) {w}
    Op 1: Im
    Op 2: Dn/(An)/ea

    Performs a logical XOR between the first immediate value and second
    operand, stores the result in the second operand

    Example: eori.l #1, (sp)+

exg
    Op 1: Dn/An
    Op 2: Dn/An

    Exchanges the values of the two operands, only works in 32 bits

    Example: exg d0, a1

ext.(l, w) {w}
    Op 1: Dn

    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

    Example: ext.w d0

jmp
    Op 1: (An)/ea

    Jumps to the specified address unconditionally

    Example: jmp (a0)

jsr
    Op 1: (An)/ea

    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

    Example: jsr (sp)

lea
    Op 1: (An)/ea
    Op 2: An

    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

    Example: lea (a0), a1

link
    Op 1: An
    Op 2: Im

    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

    Example: link a0, #-16

lsd.(b, w, l) {w}
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    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

    Example: `ls<d> #3, d7` Where d is either (l)eft or (r)ight

move.(b, w, l) {w}
    Op 1: Dn/An/(An)/Im/ea
    Op 2: Dn/(An)/An/ea

    Moves the value from the first operand to second operand. If the second
    operand is an address register, the MOVEA instruction is used instead.

    Example: move.b #10, d0

movea.(l, w) {w}
    Op 1: Dn/An/(An)/Im/ea
    Op 2: An

    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.

    Example: movea.l d0, a0

moveq
    Op 1: Im
    Op 2: Dn

    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.

    Example: moveq #10, d0

muls
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn

    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

    Example: muls d0, d1

mulu
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn

    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

    Example: mulu d5, d2

neg.(b, w, l) {w}
    Op 1: Dn/(An)/ea

    Flips the sign of the operand, depending on the specified size, defaults
    to word

    Example: neg.l d0

not.(b, w, l) {w}
    Op 1: Dn/(An)/ea

    Inverts the bits of the operand depending on the specified size

    Example: not.b d0

or.(b, w, l) {w}
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    Performs a logical OR between the first and second operand, stores the
    result in the second operand

    Example: or.l #$FF, d1

ori.(b, w, l) {w}
    Op 1: Im
    Op 2: Dn/(An)/ea

    Performs a logical OR between the first immediate value and second
    operand, stores the result in the second operand

    Example: ori.l #%1100, (a0)

pea
    Op 1: (An)/ea

    Same as lea, but it pushes the address to the stack

    Example: pea (a0)

rod.(b, w, l) {w}
    Op 1: Dn/(An)/Im/ea
    Op 2: Dn/(An)/ea

    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

    Example: `ro<d> d2, d5` Where d is either (l)eft or (r)ight

rts
    Returns from a subroutine, pops the return address from the stack and
    jumps to it

    Example: rts

scc
    Op 1: Dn/(An)/ea

    Sets the first byte of the destination operand to $FF (-1) if flags
    {condition code} is true, otherwise it sets it to 0

    Example: `s<cc> d0` Where cc is one of the condition codes

sub.(b, w, l) {w}
    Op 1: Dn/An/(An)/Im/ea
    Op 2: Dn/(An)/An/ea

    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.

    Example: sub.w $1000, d1

suba.(l, w) {w}
    Op 1: Dn/An/(An)/Im/ea
    Op 2: An

    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.

    Example: suba.w #$FF, a1

subi.(b, w, l) {w}
    Op 1: Im
    Op 2: Dn/(An)/ea

    Subtracts the immediate value to the second operand

    Example: subi #1, d3

subq.(b, w, l) {w}
    Op 1: Im
    Op 2: Dn/(An)/An/ea

    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.

    Example: subq.b #1, d3

swap
    Op 1: Dn

    Swaps the two word of the register, you can see the register as [a,b]
    after the swap it will be [b,a]

    Example: swap d0

trap
    Op 1: Im

    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 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.

    Example: trap #15

tst.(b, w, l) {w}
    Op 1: Dn/(An)/An/ea

    Compares the operand with 0

    Example: tst.b (a0)

unlk
    Op 1: An

    Sets the SP to the address register, then Pops a long value from the
    stack and stores the result in the address register

    Example: unlk a0

Directives

dc.(b, w, l)

    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

    Example: dc.b 'Hello world!', 4, %10, $F, @8, 'a', some_label

ds.(b, w, l)

    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

    Example: ds.l 100

dcb.(b, w, l)

    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

    Example: dcb.b 50, 1

org
    Sets the current position in memory for the following instructions

    Example: org $1000

equ
    Defines a constant that will be replaced by the value when the program
    is assembled

    Example: name equ 10

Addressing modes

Direct:

    Gets the content in the register directly. (the SP register is an alias
    of the a7)

    Example: d0, a0, sp

    Dn: Data register
    An: Address register

Indirect:

    Gets the value contained in memory with address being the content of the
    address register specified. Specifiying an offset by writing a number
    before the (), the addressing mode becomes indirect with displacement
    and the final address to read the memory will be (address + offset).

    Ex| (a0), 4(sp)
    (An) Indirect

Indirect Post/Pre increment:

    Gets the value contained in memory with address being the content of the
    address register specified. If it's the post increment, the address
    register will be incremented after reading the memory. If it's the pre
    increment, the address register will be incremented before reading the
    memory. The amount of increment is specified by the size of the
    instruction. In the documentation, wherever there is (An), this
    addressing mode is valid too

    Ex| (a0)+, -(sp)
    (An): Post increment
    (An): Post increment

Immediate

    Represents a numerical value, it can be a number or a label. When the
    program is assembled, the labels will be converted to the address of the
    label. Immediate values can be represented in many bases. (replace <num>
    with the actual number). Note, a string will be represented as a list of
    bytes.

    Ex| #1000, #$FF, #@14, #%10010, #'a', #'hey', #label

        Im: Immediate
        #<num>:  Decimal
        #$<num>: Hexadecimal
        #@<num>: Octal:
        #%<num>: Binary
        #'<char/string>: Text

Effective address

    Represents the address of the memory where the data is stored. It can be
    a label or a number. When the program is assembled, the labels will be
    converted to the address of the label.

    Ex| $1000, some_label, 140, %101010, @22, 'e'

    ea    Effective address
    <ea>  Effective address

Base displacement indirect

    Gets the value contained in memory with address being the sum of (address +
    offset + base), where the first register (address) will be the base address,
    the second register (base) and offset being the number before the (). In the
    documentation, wherever there is (An), this addressing mode is valid too

    Ex| 4(a0, d2), (sp, a0)

    (An) Base displacement indirect