Beispiel #1
0
def FileOnly():
    """
    These instructions only require a file register as operand.
    No range checking is done.
    When access bank selector is missing the assembler will determine the
    access bank or BSR mode for you.
    The access bank selector may only be either 0 or 1.
    """

    global Asm

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]

    value = assem.EvalExpr()[0]

    if assem.MoreParameters():
        # Good, the access bank selector is given. That's easy
        accessbank = assem.EvalExpr()[0]
        if dec.Asm.Pass == 2 and (accessbank < 0 or accessbank > 1):
            # Oops, this is not good
            errors.DoError('range', False)
    else:
        # Now we have to decide
        accessbank = 0
        if value >= dec.Asm.AccessBank18 and value <\
                (dec.Asm.AccessBank18 + 0xF00):
            # Outside of access bank range. Use BSR mode instead
            accessbank = 1

    accessbank = (accessbank & 1) << 8

    CodeWord(opcode + (value & 0x0FF) + accessbank)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    NoMore()
Beispiel #2
0
def FileFile():
    """
    MOVFF instruction. Moves a file register to a file register. Both can be
    addressed directly with 12-bits.
    Source or destination can be the W register, if the WREG SFR is used.
    The PCL, TOSU, TOSH and TOSL can't be used as destination. A range error
    is reported if you do use these.
    No other range checking is done though.
    """

    global Asm

    source = assem.EvalExpr()[0] & 0xFFF

    if not assem.MoreParameters():
        # Missing 2nd operand
        errors.DoError('missoper', False)
        dest = 0
    else:
        dest = assem.EvalExpr()[0] & 0xFFF

    CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + source)
    CodeWord(0xF000 + dest)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    if dec.Asm.Pass == 2 and dest in [0xFF9, 0xFFD, 0xFFE, 0xFFF]:
        # PCL, TOSL, TOSH and TOSU can't be used as destination
        errors.DoError('range', False)

    NoMore()
Beispiel #3
0
def Bits():
    """
    Handle Bit instructions
    Both bit set/clr as well as branch bit set/clr instructions are handled
    by this routine.
    """

    global Asm

    if MissingOperand():
        return

    bitno = assem.EvalExpr()[0]
    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] + ((bitno & 7))
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    if not assem.MoreParameters():
        # We expected more parameters
        errors.DoError('missoper', False)
        return

    param = dec.Asm.Parse_Line[dec.Asm.Parse_Pointer:dec.Asm.Parse_Pointer+2]\
        .upper()

    if param in ('A,', 'X,', 'Y,', 'A ', 'X ', 'Y '):
        assem.NowChar(True)
        if param[0] == 'A':
            mem = 255
        elif param[0] == 'X':
            mem = 128
        else:
            mem = 129
    else:
        mem = assem.EvalExpr()[0]

    if dec.Asm.Mnemonic[1] == 'R':
        # It's a branch instruction
        if not assem.MoreParameters():
            # We expected more parameters
            errors.DoError('missoper', False)
            return
        dest = assem.EvalExpr()[0]
        offset = dest - dec.Asm.BOL_Address - 3

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

    else:
        # It wasn't a branch instruction
        target.CodeByte(opcode)
        target.CodeByte(mem)

    if dec.Asm.Pass == 2:
        if (bitno < 0 or bitno > 7) or (mem < 0 or mem > 255):
            errors.DoError('range', False)

    NoMore()
Beispiel #4
0
def Lfsr():
    """
    File one of the 4 File select register pointers with a 12 bit file
    register address.
    File register number is not range checked.
    """

    global Asm

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    pointer = assem.EvalExpr()[0]

    if not assem.MoreParameters():
        # Missing operand
        errors.DoError('missoper', False)
        register = 0
    else:
        # Get the operand
        register = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2 and (pointer < 0 or pointer > 3):
        # Range error
        errors.DoError('range', False)
        pointer = pointer & 3

    CodeWord(opcode + (pointer << 4) + ((register >> 8) & 0xF))
    CodeWord(0xF000 + (register & 0xFF))

    NoMore()
Beispiel #5
0
def GetDest(filereg):
    """
    Get the destination for register file instructions.
    It can either accept W or F or nothing.
    Or it can accept any expression as long as it returns 0 or 1.
    Only when a destination is given the optional access bank selector can
    also be given. If not, the assembler will pick the proper access bank
    mode for you.
    """

    global Asm

    dest = 0x200

    if assem.MoreParameters():
        # Direction is specified

        temp = dec.Asm.Parse_Pointer

        direction = assem.GetWord().upper()
        if direction == "W":
            # Direction towards W register
            dest = 0
        elif direction == "F":
            # Direction towards File register
            dest = 0x200
        else:
            # Neither W nor F. Must be an expression now
            dec.Asm.Parse_Pointer = temp
            dest = assem.EvalExpr()[0]
            if dec.Asm.Pass == 2 and (dest < 0 or dest > 1):
                # That's a range error!
                errors.DoError('range', False)
            dest = (dest & 1) * 0x200

        if assem.MoreParameters():
            # Good, the access bank selector is given. That's easy
            accessbank = assem.EvalExpr()[0]
            if dec.Asm.Pass == 2 and (accessbank < 0 or accessbank > 1):
                # Oops, this is not good
                errors.DoError('range', False)
        else:
            # Now we have to decide
            accessbank = 0
            if filereg >= dec.Asm.AccessBank18 and filereg <\
                    (dec.Asm.AccessBank18 + 0xF00):
                # Outside of access bank range. Use BSR mode instead
                accessbank = 1

    else:
        # Direction was not specified, so access bank select is also automatic
        accessbank = 0
        if filereg >= dec.Asm.AccessBank18 and filereg <\
                (dec.Asm.AccessBank18 + 0xF00):
            # Outside of access bank range. Use BSR mode instead
            accessbank = 1

    dest += (accessbank & 1) << 8

    return dest
Beispiel #6
0
def Conditional():
    """
    Conditional instructions
    reg,dest
    con,dest
    """

    global Asm

    if MissingOperand():
        return

    val = assem.EvalExpr()[0]

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

    dest = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2:
        if (val < 0 or val > 15):
            # Range error
            errors.DoError('range', False)

# !!!! isz on last 2 locations of page causes jump to next page. Strange but
# true according to page 3-42

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (val & 15))
    target.CodeByte(dest)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    NoMore()
def FileBit():
    """
    File register and bit operations.
    Only the bit address is being range checked.
    """

    global Asm

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    filereg = assem.EvalExpr()[0]

    if assem.MoreParameters():
        # Oh, good, something else is following
        bit = assem.EvalExpr()[0]
        if dec.Asm.Pass == 2 and (bit < 0 or bit > 7):
            # Illegal bit number
            errors.DoError('range', False)
            bit = bit & 0x07
    else:
        # Oops, missing operand
        errors.DoError('missoper', False)
        bit = 0

    CodeWord(opcode + (filereg & 0x7F) + (bit << 7))

    NoMore()
Beispiel #8
0
def PointerData():
    """
    Pointer pair with data instructions
    pointer,data
    """

    global Asm

    MissingOperand()

    parsepointer = dec.Asm.Parse_Pointer
    pointer = -1

    pntr = assem.GetWord().upper()
    if len(pntr) == 2 and pntr[1] == "P":
        # It might as well be a poiner pair
        if pntr[0] >= '0' and pntr[0] <= '7':
            # It sure is
            pointer = int(pntr[0]) * 2

    if pointer == -1:
        # It wasn't a pointer, so it must be an expression now
        dec.Asm.Parse_Pointer = parsepointer
        pointer = assem.EvalExpr()[0]

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

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

    value = assem.EvalExpr()

    if prefix == '#':
        val = value[0] & 255
    elif prefix == '/':
        val = (value[0] >> 8) & 255
    elif prefix == '=':
        val = (value[0] >> 16) & 255
    else:
        val = (value[0] >> 24) & 255

    if dec.Asm.Pass == 2:
        # Range check only in pass 2
        if pointer < 0 or pointer > 15 or pointer % 2 == 1:
            # Range error
            errors.DoError('range', False)

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + pointer)
    target.CodeByte(val)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    NoMore()
Beispiel #9
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 #10
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 #11
0
def Move():

    global Asm

    if MissingOperand():
        return

    param = dec.Asm.Parse_Line[dec.Asm.Parse_Pointer:dec.Asm.Parse_Pointer+2]\
        .upper()

    if param in ('A,', 'X,', 'Y,'):
        assem.NowChar(True)
        if param == 'A,':
            dest = 255
        elif param == 'X,':
            dest = 128
        else:
            dest = 129
    else:
        dest = assem.EvalExpr()[0]

    if not assem.MoreParameters():
        # We expected more parameters
        errors.DoError('missoper', False)
        return

    prefix = assem.NowChar(True)

    if prefix not in '#/=\\':
        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(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
    target.CodeByte(dest)
    target.CodeByte(value)

    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    if dest < 0 or dest > 255:
        errors.DoError('range', False)

    NoMore()
Beispiel #12
0
def GetBit():
    """
    Legal bit addresses are:
    Direct addresses from 020H.0 to 02FH.7
    SFR addresses which can be devided by 8, followed by .0 to .7
    If the address is not followed by .0 to .7 it is handled as a normal
    address, in which case its value should be below 256.
    """

    global Asm

    pntr = dec.Asm.Parse_Pointer
    par1 = assem.GetWord().upper()
    regbit = 0

    if len(par1) > 2 and par1[-2] == '.' and par1[-1] in '01234567':
        # operand.bit notation. Hide bit number temporarily
        bitno = int(par1[-1])
        parseline = dec.Asm.Parse_Line
        dec.Asm.Parse_Line = parseline[:dec.Asm.Parse_Pointer - 2] + ' '
        dec.Asm.Parse_Pointer = pntr
        value = assem.EvalExpr()
        dec.Asm.Parse_Line = parseline
        dec.Asm.Parse_Pointer = dec.Asm.Parse_Pointer + 2

        if dec.Asm.Pass == 2:
            # Only check rage during pass 2
            if value[0] in range(0x20, 0x30):
                # In RAM area
                regbit = ((value[0] & 15) << 3) + bitno
            elif value[0] in range(0x80, 0xFF, 8):
                # In SFR area
                regbit = value[0] + bitno
            else:
                # Not in legal area
                errors.DoError('range', False)

    else:
        # No operand.bit notation, evaluate normally
        dec.Asm.Parse_Pointer = pntr
        value = assem.EvalExpr()
        regbit = value[0]

        if dec.Asm.Pass == 2 and (value[0] >> 8) != 0:
            # Value not between 0 to 255
            errors.DoError('range', False)

    return regbit
Beispiel #13
0
def Immediate2():
    """
    RLDI instruction with immediate operand.
    First operand is the register to be loaded.
    Second operand is the immediate 16 bit data.
    May be prefixed by one of the immediate prefixes.
    """

    global Asm

    if MissingOperand():
        return

    # Get register
    register = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2:
        # Don't check range in pass 1 as label may be forward referenced
        if register < 0 or register > 15:
            register = 0

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

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

    value = assem.EvalExpr()[0]

    if prefix == '#':
        val = value & 0xFFFF
    elif prefix == '/':
        val = (value >> 8) & 0xFFFF
    elif prefix == '=':
        val = (value >> 16) & 0xFFFF
    else:
        val = (value >> 24) & 0xFFFF

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] >> 8)
    target.CodeByte((dec.Asm.Instructions[dec.Asm.Mnemonic][1] & 0xFF) +
                    register)
    target.CodeByte(val >> 8)
    target.CodeByte(val & 0xFF)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    NoMore()
def Relative():

    global Asm

    if MissingOperand():
        return

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]

    value = assem.EvalExpr()[0]

    offset = value - dec.Asm.BOL_Address - 1

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

    if dec.Asm.Pass == 2:
        if offset < 0:
            offset = offset * -1
        else:
            opcode = opcode + 32
    else:
        offset = 0

    offset = (offset & 63)

    target.CodeByte(opcode + offset)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    NoMore()
Beispiel #15
0
def DirMS():
    """
    Set program memory size. It's only used to warn you when the program
    memory is full.

    Setting the memory size to 0 disables memory size checkking. This is
    useful for saving ID, Config and EERPOM data.
    """

    global Asm

    size = assem.EvalExpr()

    if size[1]:
        # A forward referenced label was used
        errors.DoError('forwref', False)
    else:
        # Not a forward refereced label
        if size[0] == 0:
            # Set memory size to infinity and beyond
            dec.Asm.Max_Address = 0x100000000
        else:
            # Not infinite size
            if size[0] > 0x200000 or size[0] < 1024:
                # That's a range error
                errors.DoError('range', False)
            dec.Asm.Max_Address = size[0] - 1

    NoMore()
Beispiel #16
0
def BranchBit():
    """
    Handle the bit test branch instructions.
    """

    global Asm

    if MissingOperand():
        # We need operands
        return

    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    par1 = GetBit()

    if not assem.MoreParameters():
        # Oops only one operand given
        errors.DoError('missoper', False)
        return

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

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

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
    target.CodeByte(par1)
    target.CodeByte(offset)

    NoMore()
Beispiel #17
0
def Returns():
    """
    The return instructions will now take an optional parameter, which controls
    whether some registers are copied from their shadow registers (1), or
    not (0).
    The default is 0.
    """

    global Asm

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    if dec.Asm.Parse_Pointer == 0 or dec.Asm.Optional is False:
        # No parameter is following
        CodeWord(opcode)
    else:
        # Optional parameter given
        flag = assem.EvalExpr()[0]

        CodeWord(opcode + (flag & 1))

        if dec.Asm.Pass == 2 and (flag < 0 or flag > 1):
            # Range error
            errors.DoError('range', False)

        NoMore()
Beispiel #18
0
def Immediate():
    """
    Immediate operand instructions.
    Instructions optionally accept the traditional # / = and \ prefixes.
    Only the RETLW instruction will accept multiple operatnds, which are
    stored sequentially in program memory.
    """

    global Asm

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    if opcode == 0x0C00:
        # Operand field may be empty for RETLW instruction
        if dec.Asm.Parse_Pointer == 0 or dec.Asm.Optional is False:
            # No parameter is following
            CodeWord(opcode)
            return

    while True:
        prefix = '#'
        if assem.NowChar() in '#/=\\':
            # A prefix is given, let's get it
            prefix = assem.NowChar(True)

        value = assem.EvalExpr()[0]

        if dec.Asm.Mnemonic == "BANKSEL":
            # BANKSEL is the same as MOVLB with modified operand
            value = (value // 256) & 0x0F

        if not dec.Flags.ErrorInLine:
            # No error in this line, let's continue
            if prefix == '#':
                # Keep lower byte
                value = value & 0xFF
            elif prefix == '/':
                # Keep 2nd lower byte
                value = (value >> 8) & 0xFF
            elif prefix == '=':
                # Keep 2nd upper byte
                value = (value >> 16) & 0xFF
            else:
                # Keep upper byte
                value = (value >> 24) & 0xFF

        if opcode == 0x0100:
            # MOVLB range is limited to 4 bits
            value = value & 0x0F

        CodeWord(opcode + value)

        if not assem.MoreParameters():
            # No more parameters
            break

        if opcode != 0x0C00:
            # Only the RETLW instruction allows multiple literal bytes
            errors.DoWarning('extrign', False)
Beispiel #19
0
def RegArg():
    """
    Expecting a register as parameter.
    A valid range from 0 to 15 is only checked in pass 2.
    """

    global Asm

    if MissingOperand():
        return

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

    if dec.Asm.Pass == 2:
        # Don't check range in pass 1 as label may be forward referenced
        if value < 0 or value > 15:
            value = 0
            errors.DoError('range', False)

        if value == 0 and opcode == 0:
            # LDN 0 is not allowed
            errors.DoError('range', False)

        if opcode == 0x60 or opcode == 0x68:
            # OUT and INP instruction have a restricted range
            if value < 1 or value > 7:
                value = 0
                errors.DoError('range', False)

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

    NoMore()
Beispiel #20
0
def Restart():

    global Asm

    if MissingOperand():
        return

    value = assem.EvalExpr()

    if dec.Flags.ErrorInLine:
        # Save dummy bute to keep passes in sync
        target.CodeByte(0)
    else:
        # No errors were found
        vector = value[0]
        if value[1] and dec.Asm.Pass == 1:
            # Don't bother about range in case of forward referenced in pass 1
            vector = 0
        if vector > 8:
            if vector not in (16, 24, 32, 40, 48, 56):
                errors.DoError('range', False)
                vector = 0
        if vector > 7:
            vector = vector >> 3

        target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] +
                        (vector << 3))

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

    global Asm

    if MissingOperand():
        return

    conditions = {'C': 1, 'NC': 2, 'Z': 3, 'NZ': 4}
    pointer = dec.Asm.Parse_Pointer
    condition = assem.GetWord().upper()
    if dec.Asm.Mnemonic == 'JR' and condition in conditions and\
                           assem.NowChar(True) == ',':
        index = conditions[condition]
    else:
        dec.Asm.Parse_Pointer = pointer
        index = 0

    value = assem.EvalExpr()
    offset = value[0] - dec.Asm.BOL_Address - 2

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

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

    NoMore()
Beispiel #22
0
def Branch(index):

    """
    Handle branch instructions.
    Displacement is destinaiton - current address - 2
    """

    global Asm

    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][index]
    if dec.Asm.Timing == 0:
        errros.DoError('badopco', False)
        return

    if MissingOperand():
        return

    value = assem.EvalExpr()
    offset = value[0] - 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])
    target.CodeByte(offset)

    NoMore()
Beispiel #23
0
def GetReg():

    global Asm

    pointer = dec.Asm.Parse_Pointer

    register = assem.GetWord().upper()

    if register == 'A':
        return (1, 0xFF)
    elif register == "X":
        return (2, 0x80)
    elif register == "Y":
        return (3, 0x81)
    elif register == "V":
        return (4, 0x82)
    elif register == "W":
        return (5, 0x83)
    elif register == "(X)":
        return (6, 0)
    elif register == "(Y)":
        return (7, 0)
    else:
        dec.Asm.Parse_Pointer = pointer
        value = assem.EvalExpr()[0]
        if dec.Asm.Pass == 2 and (value > 255 or value < 0):
            errors.DoError('range', False)
            value = value & 255

        return (0, value)
Beispiel #24
0
def BitInst():

    global Asm

    if MissingOperand():
        return

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]

    bitno = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2 and (bitno > 7 or bitno < 0):
        assem.DoError('range', False)
        bitno = bitno & 7

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

    datareg = GetReg()
    if datareg[0] > 5:
        assem.DoError('badoper', False)

    datareg = datareg[1]

    target.CodeByte(opcode + BitSwap(bitno))
    target.CodeByte(datareg)

    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

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

    global Asm

    if MissingOperand():
        return

    prefix = assem.NowChar()

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

    value = assem.EvalExpr()

    if prefix == '#':
        byte = value[0]
    elif prefix == '/':
        byte = value[0] >> 8
    elif prefix == '=':
        byte = value[0] >> 16
    else:
        byte = value[0] >> 24

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
    target.CodeByte(byte)

    NoMore()
def Pseudo():
    """
    Pseudo instructions, or compound instructions.
    These instructions combine a bit test on the status register and an INCF
    """

    global Asm

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][3]

    value = assem.EvalExpr()[0]

    if opcode == 0x0980:
        # NEGF needs to add the file address
        CodeWord(opcode + (value & 0x7F))
    else:
        # Not NEGF
        CodeWord(opcode)

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    dest = GetDest()

    CodeWord(opcode + (value & 0x7F) + dest)

    NoMore()
Beispiel #27
0
def Immediate():
    """
    Immediate operand. May be prefixed by one of the immediate prefixes.
    """

    global Asm

    if MissingOperand():
        return

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

    value = assem.EvalExpr()[0]

    if prefix == '#':
        val = value & 255
    elif prefix == '/':
        val = (value >> 8) & 255
    elif prefix == '=':
        val = (value >> 16) & 255
    else:
        val = (value >> 24) & 255

    if dec.Asm.Instructions[dec.Asm.Mnemonic][1] > 0xFF:
        # It's a 2 byte instruction
        target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] >> 8)
    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
    target.CodeByte(val)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    NoMore()
def Long():
    """
    Pseudo instructions to make jumping across page boundaries easier.
    These instructions require the maximum memory size to be set correctly
    using the dedicated .MS directive. With this information the assembler
    will only use the minimum number of required memory bank select bits.
    I deliberately don't load PCLATH directly, because that would destroy
    the contents of the W register. Instead I clear PCLATH first, then set
    only the bits necessary to select the required bank.
    """

    global Asm

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    timing = '2'

    dest = assem.EvalExpr()[0]

    if dec.Asm.Max_Address >= 2048:
        # There are multible banks

        # We now have MOVLP to load PCLATH
        CodeWord(0x3180 + ((dest >> 8) & 0x78))
        timing = '3'

    dec.Asm.Timing = timing
    CodeWord(opcode + (dest & 0x07FF))

    NoMore()
Beispiel #29
0
def Branch():
    """
    Branching is simply done by copying the second byte of the instruction
    to PCL. Therefore the destination is always on the same page as the second
    byte of the branch instruction.
    """

    global Asm

    if MissingOperand():
        return

    value = assem.EvalExpr()[0]

    if dec.Asm.Instructions[dec.Asm.Mnemonic][1] > 0xFF:
        # It's a 2 byte instruction
        target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] >> 8)
        offset = 2
    else:
        offset = 1

    if dec.Asm.Pass == 2:
        # Don't check range in pass 1 as label may be forward referenced
        page = (dec.Asm.BOL_Address + offset) >> 8
        destpage = value >> 8
        if page != destpage:
            # Destination not on the same page
            errors.DoError('range', False)

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

    NoMore()
def GetDest():
    """
    Get the destination for register file instructions.
    It can either accept W or F or nothing.
    Or it can accept any expression as long as it returns 0 or 1
    """

    global Asm

    dest = 0x80

    if assem.MoreParameters():
        # Direction is specified

        temp = dec.Asm.Parse_Pointer

        direction = assem.GetWord().upper()
        if direction == "W":
            # Direction towards W register
            dest = 0
        elif direction == "F":
            # Direction towards File register
            dest = 0x80
        else:
            # Neither W nor F. Must be an expression now
            dec.Asm.Parse_Pointer = temp
            dest = assem.EvalExpr()[0]
            if dec.Asm.Pass == 2 and (dest < 0 or dest > 1):
                # That's a range error!
                errors.DoError('range', False)
            dest = (dest & 1) * 0x80

    return dest