Beispiel #1
0
def BitInst():
    """
    Bit instructions. These require 2 operands. The first is the register
    number from 0 to 31. The second is the bit number from 0 to 7.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    reg = GetReg() << 4

    if not assem.MoreParameters():
        # Only the register number is given, the bit number is missing
        errors.DoError('missoper', False)
        # Write dummy word
        target.CodeWord(0)
        return

    bitno = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2 and (bitno < 0 or bitno > 7):
        # Report range error if bit number not between 0 and 7
        errors.DoError('range', False)
        bitno = 0

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + reg + bitno)

    NoMore()
Beispiel #2
0
def CallJmp():
    """
    CALL and JMP can reach the entire Flash memory. Therefore the constant k
    is 22 bits wide. The constant is spread over 2 words like this:

    1001.010k.kkkk.111k
            2.2111.   1
            1.0987.   6

    kkkk.kkkk.kkkk.kkkk
    1111.1100.0000.0000
    5432.1098.7654.3210

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    maxadd = dec.Asm.Max_Address
    value = assem.EvalExpr()

    if dec.Asm.Pass == 2 or (not value[1]):
        # Check range only when in pass 2 and no forward referenced label used
        if value[0] < 0 or value[0] > maxadd:
            # Are we beyond physical memory?
            errors.DoError('range', False)

    destinationl = value[0] & dec.MAX16
    destinationh = (value[0] >> 16) & 63
    destinationh = ((destinationh & 62) << 3) + (destinationh & 1)

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + destinationh)
    target.CodeWord(destinationl)

    NoMore()
Beispiel #3
0
def Spm():
    """
    This instruction has only one optional parameter. It is either Z (default)
    or Z+

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    if dec.Asm.Parse_Pointer == 0 or not dec.Asm.Optional:
        # No operand, use defalt Z index
        target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3])
    else:
        # An operand is given, must be Z or Z+
        value = GetIndex()

        if value[1] != 'Z' or value[0] == 2 or value[2] != 0:
            # Illegal index register
            errors.DoError('badoper', False)
            index = 0  # Dummy mode
        else:
            # Legal index register
            index = value[0]

        target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] +
                        (index << 4))

        NoMore()
Beispiel #4
0
def Load():

    global Asm

    if MissingOperand():
        return

    reg1 = GetReg()

    if dec.Flags.ErrorInLine:
        # An error was found in parameter 1, no need to continue
        return

    if not assem.MoreParameters():
        errors.DoError('missoper', False)
        return

    reg2 = GetReg()

    firstpar = 'LD.' + reg1[0]
    if firstpar in dec.Asm.Instructions:
        secpar = dec.Asm.Instructions[firstpar][0]
        opcode = dec.Asm.Instructions[firstpar][1]
        timing = dec.Asm.Instructions[firstpar][2]
        extra = dec.Asm.Instructions[firstpar][3]

        index = 0
        for t in secpar:
            if t == reg2[0]:
                # Found 2nd parameter, now let's save it to the target file
                opc = opcode[index]
                Code(opc)
                dec.Asm.Timing = timing[index]
                if extra[index] == 1:
                    # save one extra byte from operand 2
                    target.CodeByte(reg2[1])
                elif extra[index] == 2:
                    # save two extra bytes from operand 2
                    target.CodeWord(reg2[1])
                elif extra[index] == 3:
                    # save one extra byte from operand 1
                    target.CodeByte(reg1[1])
                elif extra[index] == 4:
                    # save one extra byte from operand 1 and one from operand 2
                    target.CodeByte(reg1[1])
                    target.CodeByte(reg2[1])
                elif extra[index] == 5:
                    # save two extra bytes from operand 1
                    target.CodeWord(reg1[1])
                NoMore()
                return
            index = index + 1

        # This type of parameter was not allowed as second parameter
        errors.DoError('badoper', False)
    else:
        # This type of parameter was not allowed as first parameter
        errors.DoError('badoper', False)
Beispiel #5
0
def LDIndexed():
    """
    LD indexed takes 2 operands. A register number and an index register,
    which may include a pre-decrement or a post-increment.
    The Y and Z index registers may also have an offset from the register's
    base value. The range of this offset is from 0 to 63.

    Reduced instructionset only has LD  Rd,Z. All others are off limits.
    This is not correctly implemented in the legacy family and cannot be fixed!

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, 1 or 0, cycles
    """

    global Asm

    reg = GetReg() << 4

    if not assem.MoreParameters():
        # Only the register was given. The index register is missing
        errors.DoError('missoper', False)
        target.CodeWord(0)  # Write dummy word
        return

    value = GetIndex()

    if value[1] == 'X':
        # Get the opcode for LD Rn,X
        if dec.Asm.AVR_Family == 6:
            # Illegal index register for this minimal core
            errors.DoError('badoper', False)
        opcode = 0x900C
    elif value[1] == 'Y':
        # Get the opcode for LD(D) Rn,Y and add offset to it
        if dec.Asm.AVR_Family == 6:
            # Illegal index register for this minimal core
            errors.DoError('badoper', False)
        opcode = 0x8008 + value[2]
        if value[0] != 0 and len(dec.Asm.Mnemonic) == 2:
            # Indicated pre-decrement or post-increment opcode
            opcode = opcode + 0x1000
    else:
        # Get the opcode for LD(D) Rn,Z and add offset to it
        opcode = 0x8000 + value[2]
        if value[0] != 0 and len(dec.Asm.Mnemonic) == 2:
            # Indicate pre-decrement or post-increment opcode
            if dec.Asm.AVR_Family == 6:
                # pre-decrement and post-increment not implemented
                errors.DoError('badoper', False)
            opcode = opcode + 0x1000

    if len(dec.Asm.Mnemonic) == 2:
        # It's LD, not LDD, add the pre-decrement or post-increment flag to it
        opcode = opcode + value[0]

    target.CodeWord(opcode + reg)

    NoMore()
Beispiel #6
0
def STIndexed():
    """
    ST indexed takes 2 operands. An index register, which may include a
    pre-decrement or a post-increment, and a register.
    The Y and Z index registers may also have an offset from the register's
    base value. The range of this offset is from 0 to 63.

    Reduced instructionset only has ST  Z,Rd. All others are off limits.
    This is not correctly implemented in the legacy family and cannot be fixed!

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, 1 or 0, cycles
    """

    global Asm

    value = GetIndex()

    if value[1] == 'X':
        # Get opcode for ST X,Rn
        if dec.Asm.AVR_Family == 6:
            # Illegal index register for this minimal core
            errors.DoError('badoper', False)
        opcode = 0x920C
    elif value[1] == 'Y':
        # Get opcode for ST(D) Y,Rn and add offset to it
        if dec.Asm.AVR_Family == 6:
            # Illegal index register for this minimal core
            errors.DoError('badoper', False)
        opcode = 0x8208 + value[2]
        if value[0] != 0 and len(dec.Asm.Mnemonic) == 2:
            # Indicated pre-decrement or post-increment opcode
            opcode = opcode + 0x1000
    else:
        # Get opcode for ST(D) Z,Rn and add offset to it
        opcode = 0x8200 + value[2]
        if value[0] != 0 and len(dec.Asm.Mnemonic) == 2:
            # Indicated pre-decrement or post-increment opcode
            if dec.Asm.AVR_Family == 6:
                # pre-decrement and post-increment not implemented
                errors.DoError('badoper', False)
            opcode = opcode + 0x1000

    if len(dec.Asm.Mnemonic) == 2:
        # It's ST, not STD, add the pre-decrement or post-increment flag to it
        opcode = opcode + value[0]

    if not assem.MoreParameters():
        errors.DoError('missoper', False)
        target.CodeWord(0)  # Write dummy word
        return

    reg = GetReg() << 4

    target.CodeWord(opcode + reg)

    NoMore()
Beispiel #7
0
def Jumps():

    global Asm

    if MissingOperand():
        return

    conditions = {
        'NZ': 0,
        'Z': 1,
        'NC': 2,
        'C': 3,
        'PO': 4,
        'PE': 5,
        'P': 6,
        'M': 7
    }
    pointer = dec.Asm.Parse_Pointer
    condition = assem.GetWord().upper()
    if condition in conditions and assem.NowChar(True) == ',':
        # Conditional jump or call
        if assem.NowChar() == " ":
            # Allow a space to follow a comma
            assem.IncParsePointer()
        value = assem.EvalExpr()
        Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][1] +
             (conditions[condition] << 3))
        target.CodeWord(value[0])
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1]
        if dec.Asm.Pass == 2 and ((value[0] >> 16) != 0):
            errors.DoErrors('range', False)
    elif condition == '(HL)':
        # (HL)
        Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][2])
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][2]
    elif condition == '(IX)':
        # (IX)
        Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][3])
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][3]
    elif condition == '(IY)':
        # (IY)
        Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][4])
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][3]
    else:
        # Non conditional
        dec.Asm.Parse_Pointer = pointer
        value = assem.EvalExpr()
        Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][0])
        target.CodeWord(value[0])
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0]

    NoMore()
Beispiel #8
0
def ELpm():
    """
    These instructions require two operands. The first one is one of the 32
    registers. The second one is either the Z index register, or Z+.
    Optionally the instruction can also be used without operands.

    Not all variants may be available on all devices. AT90S1200 doesn't have
    an LPM instruction at all.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, newflags, opcode,
                cycles
    """

    global Asm

    if dec.Asm.Parse_Pointer == 0 or not dec.Asm.Optional:
        # No operand, use implied addressing mode
        target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3])
    else:
        if dec.Asm.Mnemonic == 'ELPM':
            # Get opcode for ELMP
            opcode = 0x9006
        else:
            # Get opcode for LMP
            opcode = 0x9004

        reg = GetReg() << 4

        if not assem.MoreParameters():
            # Index register operand is missing
            errors.DoError('missoper', False)
            target.CodeWord(0)  # Write dummy word
            return

        value = GetIndex()

        if value[1] != 'Z' or value[0] == 2 or value[2] != 0:
            # Only the Z or Z+ index register is allowed.
            errors.DoError('badoper', False)
            reg = 0  # Dummy register
            index = 0  # and dummy mode
        else:
            # Legal index register
            index = value[0]

        target.CodeWord(opcode + reg + index)

        NoMore()
Beispiel #9
0
def Branch():

    global Asm

    if MissingOperand():
        return

    operand = GetOperand()

    if operand[0] == 1 or operand[0] == 2:
        # Branch relative
        offset = operand[1] - dec.Asm.BOL_Address - 2

        if dec.Asm.Pass == 2 and (offset < -128 or offset > 127):
            errors.DoError('range', False)

        target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1][0])
        target.CodeByte(offset)
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0]

    elif operand[0] == 9:
        # Branch [indirect]

        target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][1][1])
        target.CodeByte(operand[1])
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1]

    else:
        errors.DoError('badoper', False)
        return

    NoMore()
Beispiel #10
0
def LBranch():
    """
    Handle long branch instructions.
    Displacement is destinaiton - current address - 3 in case 3 byte long
    instruction
    Displacement is destinaiton - current address - 4 in case 4 byte long
    instruction
    """

    global Asm

    if MissingOperand():
        return

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    value = assem.EvalExpr()
    offset = value[0] - dec.Asm.BOL_Address - 3

    if opcode > 255:
        # It's a 2 byte opcode
        offset = offset - 1
        target.CodeByte(opcode >> 8)
    target.CodeByte(opcode)
    target.CodeWord(offset)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    NoMore()
Beispiel #11
0
def Stack():

    global Asm

    if MissingOperand():
        return

    operand = assem.GetWord().upper()

    if operand == 'A':
        index = 0
    elif operand == 'X':
        index = 1
    elif operand == 'Y':
        index = 2
    elif operand == 'CC':
        index = 3
    else:
        errors.DoError('badoper', False)
        return

    opcode = (dec.Asm.Instructions[dec.Asm.Mnemonic][1][index])
    if opcode > 255:
        target.CodeWord(opcode)
    else:
        target.CodeByte(opcode)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][index]

    NoMore()
Beispiel #12
0
def Multiply():

    global Asm

    if MissingOperand():
        return

    operand1 = assem.GetWord().upper()

    if operand1 not in 'XY':
        errors.DoError('badoper', False)
        return

    if not assem.MoreParameters():
        errors.DoError('missoper', False)
        return

    if assem.NowChar(True).upper() != 'A':
        errors.DoError('badoper', False)
        return

    if operand1 == 'X':
        target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1][0])
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0]
    else:
        target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][1][1])
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1]

    NoMore()
Beispiel #13
0
def RegOnly():
    """
    These instructions require only one register.
    CRL, LSL, ROL and TST are acutally pseudo instructions. They require
    the single operand to be used twice, both as source and destinatio.
    The SER instruction has a limited register span.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    reg = GetReg()

    if dec.Asm.Mnemonic in ('CLR', 'LSL', 'ROL', 'TST'):
        # These are acutally pseudo instructions, requiring the operand
        # to be used as source and destination for the original instruction
        reg1 = reg << 4
        if reg > 15:
            reg = reg - 16 + 512
        reg = reg + reg1
    elif dec.Asm.Mnemonic == 'SER':
        if dec.Asm.Pass == 2 and reg < 16:
            # This one has a limited register span
            errors.DoError('range', False)
        reg = (reg & 0xF) << 4
    else:
        # All others are normal
        reg = reg << 4

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + reg)

    NoMore()
Beispiel #14
0
def Jumps():

    global Asm

    if MissingOperand():
        return

    if assem.NowChar() == '@':
        # It is an indirect jump

        reg1 = GetReg()

        if reg1[0] == '@rr' or reg1[0] == '@R':
            target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1][1])
            target.CodeByte(reg1[1])
            dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1]
            if reg1[1] & 1 != 0:
                errors.DoError('range', False)
        else:
            errors.DoError('badoper', False)
    else:
        # It's not an indirect jump
        if dec.Asm.Mnemonic == 'CALL':
            # It's a CALL instruction
            opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][0]
            dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0]

        else:
            # It's JP instruction
            conditions = {'F': 0x00, 'C': 0x70, 'NC': 0xF0, 'Z': 0x60,
                          'NZ': 0xE0, 'PL': 0xD0, 'MI': 0x50, 'OV': 0x40,
                          'NOV': 0xC0, 'EQ': 0x60, 'NE': 0xE0, 'GE': 0x90,
                          'LT': 0x10, 'GT': 0xA0, 'LE': 0x20, 'UGE': 0xF0,
                          'ULT': 0x70, 'UGT': 0xB0, 'ULE': 0x30}

            pointer = dec.Asm.Parse_Pointer
            cond = assem.GetWord().upper()

            if cond in conditions and assem.NowChar() == ',':
                # A legal condition code was given
                opcode = conditions[cond] + 13
                dec.Asm.Timing = '10+'
                if not assem.MoreParameters():
                    errors.DoError('missoper', False)
                    return
            else:
                # No condition was given
                dec.Asm.Parse_Pointer = pointer
                dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0]
                opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][0]

        dest = assem.EvalExpr()

        target.CodeByte(opcode)
        target.CodeWord(dest[0])
        if dec.Asm.Pass == 2 and (dest[0] >> 16) != 0:
            errors.DoError('range', False)

    NoMore()
Beispiel #15
0
def InOut():
    """
    These instructions require two operands. A register from 0 to 31 and an
    I/O address from 0 to 63. The IN and OUT instructions have their operand
    order swapped.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    if dec.Asm.Mnemonic == 'IN':
        # Get register operand first, then I/O location
        reg = GetReg() << 4

        if not assem.MoreParameters():
            # Oops only register is given
            errors.DoError('missoper', False)
            target.CodeWord(0)  # Write dummy word
            return

        value = assem.EvalExpr()[0]

    else:
        # Get I/O location first, then register
        value = assem.EvalExpr()[0]

        if not assem.MoreParameters():
            # Oops, only I/O location given
            errors.DoError('missoper', False)
            target.CodeWord(0)  # Write dummy word
            return

        reg = GetReg() << 4

    if dec.Asm.Pass == 2 and (value < 0 or value > 63):
        # Check I/O address range in pass 2 only
        errors.DoError('range', False)
        value = 0

    ioreg = (value & 15) + ((value & 48) << 5)

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + reg + ioreg)

    NoMore()
Beispiel #16
0
def Inherent():
    """
    These instructions don't need an operand. Can't be any easier.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3])
Beispiel #17
0
def RelJmp():
    """
    Relative addressing mode. Most instructions have an offset range from
    -64 to +63, counted from the begin of line address + 1.
    Only the RCALL and RJMP instructions have a range between 2048 and
    +2047.
    BRBC and BRBS als require a bit number to specified as first operand.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    if dec.Asm.Mnemonic in ('BRBC', 'BRBS'):
        # Get bit number first
        value = assem.EvalExpr()
        bit = value[0]
        if dec.Asm.Pass == 2 and (bit < 0 or bit > 7):
            # Test range of bit number (0 to 7)
            errors.DoError('range', False)
        bit = bit & 7
        if not assem.MoreParameters():
            # Only bit number was given
            errors.DoError('missoper', False)
    else:
        # All other instructions don't require a bit number
        bit = 0

    value = assem.EvalExpr()

    if dec.Asm.Pass == 2 or (not value[1]):
        # Check range only when in pass 2 and no forward referenced label used
        if value[0] < 0 or value[0] > dec.Asm.Max_Address:
            # Are we beyond physical memory?
            errors.DoError('range', False)

    offset = value[0] - dec.Asm.BOL_Address - 1

    if dec.Asm.Mnemonic in ('RCALL', 'RJMP'):
        # RCALL and RCJMP have an extended range
        if dec.Asm.Pass == 2 and (offset < -2048 or offset > 2047):
            # Out of range
            errors.DoError('range', False)
        offset = offset & 0xFFF
    else:
        # All other relative jump instructions have a limited range
        if dec.Asm.Pass == 2 and (offset < -64 or offset > 63):
            # Out of range
            errors.DoError('range', False)
        offset = (offset & 0x7F) << 3

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + offset + bit)

    NoMore()
Beispiel #18
0
def IOBits():
    """
    I/O instructions. Operate on the lower 32 I/O addresses. Requires two
    operands. I/O address, from 0 to 31. And bit number from 0 to 7.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    ioreg = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2 and (ioreg < 0 or ioreg > 31):
        # Check range of I/O register in pass 2 only
        errors.DoError('range', False)
        ioreg = 0

    ioreg = ioreg << 3

    if not assem.MoreParameters():
        # Only the I/O register is given. The bit number is missing
        errors.DoError('missoper', False)
        # Write dummy word
        target.CodeWord(0)
        return

    bitno = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2 and (bitno < 0 or bitno > 7):
        # Check range of bit number in pass 2 only
        errors.DoError('range', False)
        bitno = 0

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + ioreg + bitno)

    NoMore()
Beispiel #19
0
def SaveAll(prebyte, opcode, operand):

    if opcode == 0:
        errors.DoError('badoper', False)
        return

    if prebyte != 0:
        target.CodeByte(prebyte)
    target.CodeByte(opcode)

    if operand[0] in (0, 1, 4, 7, 9, 10, 11, 12, 13, 14):
        target.CodeByte(operand[1])
    elif operand[0] in (2, 5, 8):
        target.CodeWord(operand[1])

    NoMore()
def Jumps():
    """
    Jump instructions
    - Absolute
    - [#,X]
    """

    global Asm

    if MissingOperand():
        return

    if assem.NowChar() == '[':
        # Should be [#,X] now
        assem.IncParsePointer()
        opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][1]
        if opcode == 0:
            errors.DoError('badoper', False)
            return
        else:
            if assem.NowChar() == '#':
                # Ignore leading #
                assem.IncParsePointer()
            value = assem.EvalExpr()[0]
            target.CodeByte(opcode)
            target.CodeByte(value)
            dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1]
            if not assem.MoreParameters():
                errors.DoError('missoper', False)
            if dec.Asm.Parse_Line[dec.Asm.Parse_Pointer:dec.Asm.Parse_Pointer +
                                  3].upper() != 'X] ':
                errors.DoError('badoper', False)
            return

    else:
        # Must be absolute now
        dest = assem.EvalExpr()[0]
        target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1][0])
        target.CodeWord(dest)
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1]

        if dec.Asm.Pass == 2 and (dest < dec.Ace_Minjmp
                                  or dest > dec.Ace_Maxjmp):
            errors.DoError('range', False)

    NoMore()
def Jumps():

    global Asm

    if MissingOperand():
        return

    dest = assem.EvalExpr()

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
    target.CodeWord(dest[0])
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    if dec.Asm.Pass == 2 and (dest[0] >> 14) != 0:
        errors.DoError('range', False)

    NoMore()
Beispiel #22
0
def Sreg():
    """
    These instructions require only a bit number from 0 to 7.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    sregbit = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2 and (sregbit < 0 or sregbit > 7):
        # Outside the legal range
        errors.DoError('range', False)
        sregbit = 0

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + (sregbit << 4))

    NoMore()
Beispiel #23
0
def Des():
    """
    This instruction requires an operand in the range of 0 to 15.

    Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles
    """

    global Asm

    value = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2 and (value < 0 or value > 15):
        # Outside the legal range
        errors.DoError('range', False)
        value = 0

    target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + (value << 4))

    NoMore()
Beispiel #24
0
def Sweet16():
    """
    Handle remaining Sweet16 instructions. They all expect a register number,
    some accept an indirect register number. Only the SET instruction also
    expects a 16 bit target address.
    Registers are numbered from 0 to 15. If you want to use R0 to R15 instead
    assign labels to the 16 register numbers.
    """

    global Asm

    if MissingOperand():
        return

    if assem.NowChar() == '@':
        assem.IncParsePointer()
        opcode = Sweet16_Mnemonics[dec.Asm.Mnemonic][2]
    else:
        opcode = Sweet16_Mnemonics[dec.Asm.Mnemonic][1]

    if opcode == 0:
        errors.DoError('badopco', False)
        return

    value = assem.EvalExpr()
    if dec.Asm.Pass == 2 and (value[0] >> 4) != 0:
        errors.DoError('range', False)

    opcode = opcode + (value[0] & 15)

    target.CodeByte(opcode)

    if dec.Asm.Mnemonic == 'SET':
        if assem.MoreParameters():
            value = assem.EvalExpr()
            target.CodeWord(value[0])
        else:
            errors.DoError('missoper', False)

    NoMore()
Beispiel #25
0
def Absolute():

    global Asm

    if MissingOperand():
        return

    value = assem.EvalExpr()

    if dec.Asm.Pass == 2 or (not value[1]):
        # Test range only if in pass 2, or pass 1 if not forward referenced
        if value[0] > dec.Asm.Max_Address or value[0] < 0:
            # It's a range error, simply ignore everything which doesn't fit
            errors.DoError('range', False)

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
    target.CodeWord(value[0])

    if value[2] == 2:
        errors.DoWarning('eeprom')

    NoMore()
Beispiel #26
0
def Jumps():

    global Asm

    if dec.Asm.Mnemonic == 'CPE':
        # This mnemonics may or may not have an address as operand
        # Depending on the 1972 or 1976 syntax
        if not dec.Asm.Optional:
            # No parameter was following within 10 spaces
            target.CodeByte(0xBC)
            dec.Asm.Timing = "5"
            return

    dest = assem.EvalExpr()

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
    target.CodeWord(dest[0])

    if dec.Asm.Pass == 2 and (dest[0] >> 14) != 0:
        errors.DoError('range', False)

    NoMore()
Beispiel #27
0
def InOut():

    global Asm

    if MissingOperand():
        return

    value = assem.EvalExpr()

    if dec.Flags.ErrorInLine:
        # Save 2 dummy bytes if an error was given
        target.CodeWord(0)
    else:
        # No error was found, no danger of getting sync error
        if dec.Asm.Pass == 2 or (not value[1]):
            # Test range in pass 2 or when not forward referenced
            if value[0] > dec.MAX8 or value[0] < 0:
                # Report error, but ignore everthing which doesn't fit
                errors.DoError('range', False)
        target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
        target.CodeByte(value[0])

    NoMore()
Beispiel #28
0
def Accu():

    global Asm

    if MissingOperand():
        return

    if GetOperand()[0] != 15:
        errors.DoError('badoper', False)
        return

    if not assem.MoreParameters():
        errors.DoError('missoper', False)
        return

    operand = GetOperand()
    if operand[0] > 14:
        errors.DoError('badoper', False)
        return

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][operand[0]]
    timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][operand[0]]
    prebyte = opcode // 256
    opcbyte = opcode % 256

    if prebyte != 0:
        target.CodeByte(prebyte)
    target.CodeByte(opcbyte)

    if operand[0] in (0, 1, 4, 7, 9, 10, 11, 12, 13, 14):
        target.CodeByte(operand[1])
    elif operand[0] in (2, 5, 8):
        target.CodeWord(operand[1])

    dec.Asm.Timing = timing

    NoMore()
Beispiel #29
0
def Immediate():

    global Asm

    if MissingOperand():
        return

    if dec.Asm.Mnemonic == 'LXI':
        registers = 'BDHS'
        reg = registers.find(assem.NowChar(True).upper())

        if reg < 0:
            errors.DoError('badoper', False)
            return
        if reg == 3:
            # It was S, so next char must be a P to finish SP
            if assem.NowChar(True).upper() != 'P':
                errors.DoError('badoper', False)
                return
        opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (reg << 4)
        if not assem.MoreParameters():
            errors.DoError('missoper', False)
    elif dec.Asm.Mnemonic == 'MVI':
        registers = 'BCDEHLMA'
        reg = registers.find(assem.NowChar(True).upper())
        timing = dec.Asm.Timing.split(':')
        if reg == 6:
            dec.Asm.Timing = timing[1]
        else:
            dec.Asm.Timing = timing[0]
        if reg < 0:
            errors.DoError('badoper', False)
            return
        opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (reg << 3)
        if not assem.MoreParameters():
            errors.DoError('missoper', False)
    else:
        opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]

    prefix = ''
    if assem.NowChar() in '#/=\\':
        prefix = assem.NowChar(True)

    value = assem.EvalExpr()

    if not dec.Flags.ErrorInLine:
        target.CodeByte(opcode)

        if dec.Asm.Mnemonic == 'LXI':
            if prefix in ' #':
                target.CodeWord(value[0])
            elif prefix == '/':
                target.CodeWord(value[0] >> 8)
            elif prefix == '=':
                target.CodeWord(value[0] >> 16)
            else:
                target.CodeWord(value[0] >> 24)
        else:
            if prefix in ' #':
                target.CodeByte(value[0])
            elif prefix == '/':
                target.CodeByte(value[0] >> 8)
            elif prefix == '=':
                target.CodeByte(value[0] >> 16)
            else:
                target.CodeByte(value[0] >> 24)

    NoMore()
def Multi():
    """
    Handle multiple operand type instructions
    - Immediate mode
    - Direct page mode
    - Extended mode
    - 0,X mode
    - Direct,X mode
    - Extended,X mode
    """

    global Asm

    if MissingOperand():
        return

    if assem.NowChar() in '#/=\\':
        # It is direct addressing mode
        prefix = assem.NowChar(True)
        opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][0]
        if opcode == 0:
            errors.DoError('badoper', False)
            return

        value = assem.EvalExpr()[0]
        if prefix == '/':
            value = value >> 8
        elif prefix == '=':
            value = value >> 16
        elif prefix == '\\':
            value = value >> 24

        Code(opcode)
        target.CodeByte(value)
        dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0]

        NoMore()
        return

    if assem.NowChar() == ',':
        # zero offset indexed mode
        value = 0
        length = 0
        assem.MoreParameters()
        indexreg = assem.GetWord().upper()
        if indexreg == 'X':
            # Use 0 offset X mode
            index = 3
        else:
            errors.DoError('badoper', False)
            return

    elif dec.Asm.Parse_Line[dec.Asm.Parse_Pointer:dec.Asm.Parse_Pointer+2]\
            .upper() == 'X ':
        # Zero offset indexed X mode
        value = 0
        length = 0
        index = 3
        assem.IncParsePointer()

    else:
        # Can be direct mode, extended mode or offset,indexed mode from here
        prefix = ''
        if assem.NowChar() in '<>':
            prefix = assem.NowChar(True)

        dest = assem.EvalExpr()
        value = dest[0]

        if assem.MoreParameters():
            # Handle indexed mode
            indexreg = assem.GetWord().upper()
            if indexreg == 'X':
                index = 4
            else:
                errors.DoError('badoper', False)
                return

            if prefix == '>':
                # Forced extended mode
                if dec.Asm.Instructions[dec.Asm.Mnemonic][1][index + 1] == 0:
                    # Extended mode doesn't exist, use direct mode instead
                    length = 1
                else:
                    index = index + 1
                    length = 2
            elif prefix == '<':
                # Forced direct mode
                length = 1
            else:
                # Let the assembler deside whether it's direct or extended
                if dest[1]:
                    # Forward referenced label used, use extended
                    if dec.Asm.Instructions[dec.Asm.Mnemonic][1][index +
                                                                 1] == 0:
                        # Extended mode doesn't exist, use direct mode instead
                        length = 1
                    else:
                        length = 2
                        index = index + 1
                else:
                    if value == 0 and index == 4:
                        # 0 offset and X index, use special opcode if it exists
                        if dec.Asm.Instructions[dec.Asm.Mnemonic][1][index-1]\
                                == 0:
                            # Sorry, doesn't exist
                            length = 1
                        else:
                            length = 0
                            index = index - 1
                    elif value > 255:
                        # We should use extended indexed mode
                        if dec.Asm.Instructions[dec.Asm.Mnemonic][1][index+1]\
                                == 0:
                            # But that doesn't exist
                            errors.DoError('range', False)
                            return
                        index = index + 1
                        length = 2
                    else:
                        # We can use Direct mode
                        length = 1

        else:
            # Direct or extended mode
            if prefix == '>':
                # Forced extended mode
                if dec.Asm.Instructions[dec.Asm.Mnemonic][1][2] == 0:
                    # Extended mode doesn't exist, use direct mode instead
                    index = 1
                    length = 1
                else:
                    # Extended mode exists, feel free to use it
                    index = 2
                    length = 2
            elif prefix == '<':
                # Forced direct mode
                index = 1
                length = 1
            else:
                # Let the assembler deside whether it's direct or extended
                if dest[1]:
                    # Forward referenced label used, use extended
                    if dec.Asm.Instructions[dec.Asm.Mnemonic][1][2] == 0:
                        # Extended mode doesn't exist, use direct mode instead
                        index = 1
                        length = 1
                    else:
                        # Extended mode does exist, feel free to use it
                        index = 2
                        length = 2
                else:
                    if value > 255:
                        index = 2
                        length = 2
                    else:
                        index = 1
                        length = 1

            if dec.Asm.Pass == 2 and length == 1:
                # We are using direct mode, does the value fit?
                if value >= 255:
                    errors.DoError('range', False)
            if dec.Asm.Pass == 2 and value < 0:
                # Negative numbers not allowed
                errors.DoError('range', False)

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][index]
    if opcode == 0:
        errors.DoError('badoper', False)
        return
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][index]
    Code(opcode)

    if length == 1:
        target.CodeByte(value)
    elif length == 2:
        target.CodeWord(value)

    NoMore()