예제 #1
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]
        if assem.NowChar() == " ":
            # Allow a space to follow a comma
            assem.IncParsePointer()
    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()
예제 #2
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()
예제 #3
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)
예제 #4
0
def RegPair():

    global Asm

    if MissingOperand():
        return

    registers = 'BDHS'
    if dec.Asm.Mnemonic in ('POP', 'PUSH'):
        registers = 'BDHP'

    reg = registers.find(assem.NowChar(True).upper())

    if reg < 0:
        errors.DoError('badoper', False)
        return

    if reg == 3:
        wrong = False
        if dec.Asm.Mnemonic in ('POP', 'PUSH'):
            if assem.NowChar(True).upper() != 'S':
                wrong = True
            else:
                if assem.NowChar(True).upper() != 'W':
                    wrong = True
        else:
            if assem.NowChar(True).upper() != 'P':
                wrong = True
        if wrong:
            errors.DoError('badoper', False)
            return

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (reg << 4))

    NoMore()
예제 #5
0
def Immediate():

    global Asm

    if MissingOperand():
        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

    WriteOpcode(dec.Asm.Instructions[dec.Asm.Mnemonic][1])
    WriteOperand(val)
    dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2]

    NoMore()
예제 #6
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()
예제 #7
0
def ImmediateNibl():
    """
    Immediate Nibble instructions (test included in mnemonic)
    data
    """

    global Asm

    if MissingOperand():
        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

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

    NoMore()
예제 #8
0
def GetParameters():

    global Asm

    parameters = []

    if dec.Asm.Parse_Pointer == 0 or assem.NowChar() in dec.COMMENT2:
        # No operand field or operand field is only comment
        return parameters

    while True:
        parameter = GetOneParameter()
        parameters.append(parameter)
        if assem.NowChar() == " ":
            # End of parameter list
            break
        if assem.NowChar(True) == ",":
            # Something more follows
            if assem.NowChar() == " ":
                # A space followed the comma. We allow one space for
                # readability
                assem.IncParsePointer()
            if assem.NowChar() in " ;":
                # Nothing else follows, save final empty parameter
                parameters.append("")
                break

    return parameters
예제 #9
0
파일: crz8.py 프로젝트: Ivoah/6502
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()
예제 #10
0
def Immediate():
    """
    Immediate operand instructions.
    Instructions optionally accept the traditional # / = and \ prefixes.
    Only GOTO and CALL don't, they are only tolerant to the # prefix
    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 == 0x3400:
        # 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()

        if not dec.Flags.ErrorInLine:
            # No error in this line, let's continue
            if opcode == 0x2000 or opcode == 0x2800:
                # Allow 11 bits of operand for GOTO
                CodeWord(opcode + (value[0] & 0x7FF))
                if prefix != '#':
                    # Only the default prefix is allowed
                    errors.DoError('badoper', False)
            elif prefix == '#':
                # Save opcode and lower byte
                CodeWord(opcode + (value[0] & 0xFF))
            elif prefix == '/':
                # Save opcode and 2nd lower byte
                CodeWord(opcode + ((value[0] >> 8) & 0xFF))
            elif prefix == '=':
                # Save opcode and 2nd upper byte
                CodeWord(opcode + ((value[0] >> 16) & 0xFF))
            else:
                # Save opcode and upper byte
                CodeWord(opcode + ((value[0] >> 24) & 0xFF))

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

        if opcode != 0x3400:
            # Only the RETLW instruction allows multiple literal bytes
            errors.DoWarning('extrign', False)
예제 #11
0
def GetIndex():
    """
    Get an index register.
    Legal index registers are X, Y and Z.
    These register may be pre-decremented or post-incremented.

    Function returns a tupple:
        incdec:  0=unchanged, 1=post-increment, 2=pre-decement
        index: X, Y, or Z
        offset: 6-bit offset in range from 0 to 63
    """

    global Asm

    index = assem.NowChar(True).upper()

    if index == ' ':
        # Mmm, missing operand
        errors.DoError('missoper', False)
        return (0, 'Z', 0)  # Return dummy values

    incdec = 0
    if index == '-':
        # Pre-decrement
        incdec = 2
        index = assem.NowChar(True).upper()

    if index not in ('X', 'Y', 'Z'):
        # It's none of the legal index registers
        errors.DoError('badoper', False)
        return (0, 'Z', 0)  # Return dummy values

    if incdec == 0:
        # It's not pre-decrement, so it may be post-incrment
        if assem.NowChar() == '+':
            incdec = 1
            assem.NowChar(True)

    offset = 0
    if dec.Asm.Mnemonic in ('LDD', 'STD') and incdec == 1:
        # An offset q must follow
        if index == 'X':
            # LDD X+q doesn't exist
            errors.DoError('badoper', False)
        offset = assem.EvalExpr()[0]

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

        # Split all the bits to fit the opcode gaps.
        offset = (offset & 7) + ((offset & 0x18) << 7) + ((offset & 0x20) << 8)

    return (incdec, index, offset)
예제 #12
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()
예제 #13
0
def Pairs():
    """
    Handle paired operand instructions.
    """

    global Asm

    if MissingOperand():
        return

    reg1 = assem.GetWord().upper()

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

    if assem.NowChar() == ' ':
        errors.DoError('missoper', False)
        return

    if assem.NowChar() in '#/=\\':
        reg2 = '#'
    else:
        reg2 = assem.GetWord().upper()

    operand = reg1 + ',' + reg2

    operands = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    opcodes = dec.Asm.Instructions[dec.Asm.Mnemonic][2]
    times = dec.Asm.Instructions[dec.Asm.Mnemonic][3]

    if operand in operands:
        index = 0
        for t in operands:
            if t == operand:
                break
            index = index + 1
        target.CodeByte(opcodes[index])
        dec.Asm.Timing = times[index]
        if reg2 == '#':
            prefix = assem.NowChar(True)
            value = assem.EvalExpr()
            if prefix == '#':
                target.CodeByte(value[0])
            elif prefix == '/':
                target.CodeByte(value[0] >> 8)
            elif prefix == '=':
                target.CodeByte(value[0] >> 16)
            else:
                target.CodeByte(value[0] >> 24)
    else:
        errors.DoError('badoper', False)

    NoMore()
예제 #14
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()
예제 #15
0
def Immediate():

    global Asm

    if MissingOperand():
        return

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

    dest = GetReg()

    if dest[0] > 5:
        errors.DoError('badoper', False)
        return

    if len(opcode[dest[0]]) == 0:
        errors.DoError('badoper', False)
        return

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

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

    value = assem.EvalExpr()

    for i in range(0, len(opcode[dest[0]]), 2):
        byte = opcode[dest[0]][i:i + 2]
        if byte == 'XX':
            target.CodeByte(dest[1])
        else:
            target.CodeByte(int(byte, 16))

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

    target.CodeByte(data)

    dec.Asm.Timing = timing[dest[0]]

    NoMore()
예제 #16
0
def MviInst():

    global Asm

    if MissingOperand():
        return

    registers = 'ABCDEHLM'

    reg1 = registers.find(assem.NowChar(True).upper())

    if reg1 < 0:
        errors.DoError('badoper', False)
        return

    if reg1 == 7:
        # timing is different if first operand is M
        dec.Asm.Timing = '9'

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

    if assem.NowChar() == ' ':
        errors.DoError('missoper', False)
        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

    NoMore()

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (reg1 << 3)

    target.CodeByte(opcode)
    target.CodeByte(byte)
예제 #17
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()
예제 #18
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()
예제 #19
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()
예제 #20
0
def Pseudo():

    global Asm

    ptr = GetPtr()

    if ptr > 0:
        # Legal pointer used
        if assem.NowChar(True) == ",":
            # A parameter is following
            dest = assem.EvalExpr()[0] - 1
            # LDI /DEST
            WriteOpcode(0xC4)
            WriteOperand((dest >> 8) & 255)
            # XPAH PTR
            WriteOpcode(0x34 + ptr)
            # LDI #DEST
            WriteOpcode(0xC4)
            WriteOperand(dest & 255)
            # XPAL PTR
            WriteOpcode(0x30 + ptr)
            # XPPC PTR
            WriteOpcode(0x3C + ptr)
    else:
        # PC or P0 not allowed
        errors.DoError('badoper', False)
        return

    NoMore()
예제 #21
0
def Math():

    global Asm

    timing = dec.Asm.Timing.split(':')

    if MissingOperand():
        return

    registers = 'BCDEHLMA'

    reg = registers.find(assem.NowChar(True).upper())

    if reg == 6:
        dec.Asm.Timing = timing[1]
    else:
        dec.Asm.Timing = timing[0]

    if dec.Asm.Mnemonic in ('DCR', 'INR'):
        reg = reg << 3

    if reg < 0:
        errors.DoError('badoper', False)
        return

    NoMore()

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + reg)
예제 #22
0
def XchdInst():
    """
    Handle the XCHD instruction.
    """

    global Asm

    if MissingOperand():
        # No parameters
        return

    dec.Asm.Timing = '1'

    if assem.NowChar(True).upper() != 'A':
        # First paramter must be an A
        errors.DoError('badoper', False)
        return

    if not assem.MoreParameters():
        # Only one parameter given
        errors.DoError('missoper', False)
        return

    par2 = GetReg()

    if par2[1] != 3:
        # Second parameter may only be @Ri
        errors.DoError('badoper', False)
        return

    target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + par2[0])

    NoMore()
예제 #23
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()
예제 #24
0
def MovInst():

    global Asm

    if MissingOperand():
        return

    registers = 'ABCDEHLM'

    reg1 = registers.find(assem.NowChar(True).upper())

    if reg1 < 0:
        errors.DoError('badoper', False)
        return

    if reg1 == 7:
        # timing is different if first operand is M
        dec.Asm.Timing = '7'

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

    if assem.NowChar() == ' ':
        errors.DoError('missoper', False)
        return

    reg2 = registers.find(assem.NowChar(True).upper())

    if reg2 < 0:
        errors.DoError('badoper', False)
        return

    if reg1 == 7 and reg2 == 7:
        # mov m,m is not allowed, that his the hlt instruction
        errors.DoError('badoper', False)
        return

    if reg2 == 7:
        # timing is different if second operand is M
        dec.Asm.Timing = '8'

    NoMore()

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (reg1 << 3) + reg2

    target.CodeByte(opcode)
예제 #25
0
def DirID():

    """
    Set the ID words.
    These ID words are usually stored directly behind the program memory, or
    directly behind the EEPROM memory if that is present.
    The SB-Assembler only checks that the Configuration word is stored beyond
    the program memory.
    """

    global Asm, Cross

    if dec.Asm.Memory != 0:
        # The .ID directive can only be used in program memory
        errors.DoError(dec.Cross.Name + 'codemem', False)
        return

    if dec.Asm.PH_Address <= dec.Asm.Max_Address:
        # We're still in program memory. We can't have that
        errors.DoError(dec.Cross.Name + 'progmem', False)
        return

    if assem.NowChar() == '#':
        # Ignore the # symbol
        assem.NowChar(True)

    id = assem.EvalExpr()[0]

    # Temporarily raise program limit
    limit = dec.Asm.Max_Address
    dec.Asm.Max_Address = 0x0FFF

    # Save the ID, one nibble at a time
    target.SaveByte(id & 0x000F)
    target.SaveByte(0)
    target.SaveByte((id >> 4) & 0x000F)
    target.SaveByte(0)
    target.SaveByte((id >> 8) & 0x000F)
    target.SaveByte(0)
    target.SaveByte((id >> 12) & 0x000F)
    target.SaveByte(0)

    # Restore original limit
    dec.Asm.Max_Address = limit

    NoMore()
예제 #26
0
def MovInst():

    global Asm

    timing = dec.Asm.Timing.split(':')

    if MissingOperand():
        return

    registers = 'BCDEHLMA'

    reg1 = registers.find(assem.NowChar(True).upper())

    if reg1 < 0:
        errors.DoError('badoper', False)
        return

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

    if assem.NowChar() == ' ':
        errors.DoError('missoper', False)
        return

    reg2 = registers.find(assem.NowChar(True).upper())

    if reg2 < 0:
        errors.DoError('badoper', False)
        return

    if reg1 == 6 and reg2 == 6:
        # mov m,m is not allowed, that's the hlt instruction
        errors.DoError('badoper', False)
        return

    NoMore()

    opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (reg1 << 3) + reg2

    if reg1 == 6 or reg2 == 6:
        dec.Asm.Timing = timing[1]
    else:
        dec.Asm.Timing = timing[0]

    target.CodeByte(opcode)
예제 #27
0
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()
예제 #28
0
def GetOneParameter():

    global Asm

    parameter = ""

    if assem.NowChar() == ",":
        # It is an empty parameter
        return parameter
    endmark = assem.NowChar()
    if endmark in "'\"":
        # Start of literal string
        assem.IncParsePointer()
        while assem.NowChar() != endmark:
            # Get parameter until end mark
            singlechar = assem.NowChar(True)
            if singlechar == "\\":
                # Escaping, include the Escape symbol in parameter
                parameter = parameter + singlechar
                # And add the Escaped character too
                singlechar = assem.NowChar(True)
            parameter = parameter + singlechar
        assem.IncParsePointer()  # Increment past endmark
        return parameter
    else:
        # Get parameter until space or comma
        while not assem.NowChar() in " ,":  # Can never be beyond end line!
            parameter = parameter + assem.NowChar()
            assem.IncParsePointer()
        return parameter
예제 #29
0
def DirCW():

    """
    Set the Configuration word.
    This Configuration word is usually stored at the last location in memory,
    which is word address $0FFF (or byte addresses ($1FFE and $1FFF).
    Programming devices expect that word to be there. The SB-Assembler only
    checks that the Configuration word is stored beyond the program memory.
    """

    global Asm, Cross

    if dec.Asm.Memory != 0:
        # The .CW directive can only be used in program memory
        errors.DoError(dec.Cross.Name + 'codemem', False)
        return

    if dec.Asm.PH_Address <= dec.Asm.Max_Address:
        # We're still in program memory. We can't have that
        errors.DoError(dec.Cross.Name + 'progmem', False)
        return

    if assem.NowChar() == '#':
        # Ignore the # symbol
        assem.NowChar(True)

    config = assem.EvalExpr()[0]

    if dec.Asm.Pass == 2 and (config < 0 or config > 0x0FFF):
        # Only 12 bits allowed
        errors.DoError('range', False)

    # Temporarily raise program limit
    limit = dec.Asm.Max_Address
    dec.Asm.Max_Address = 0x0FFF

    # Bypass the RETLW pointer
    target.SaveByte(config & 0xFF)
    target.SaveByte((config >> 8) & 0x0F)

    # Restore original limit
    dec.Asm.Max_Address = limit

    NoMore()
예제 #30
0
def LdaxStax():

    global Asm

    if MissingOperand():
        return

    reg = assem.NowChar(True).upper()

    if reg == 'B':
        opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1]
    elif reg == 'D':
        opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (1 << 4)
    else:
        errors.DoError('badoper', False)
        return

    NoMore()

    target.CodeByte(opcode)