Ejemplo n.º 1
0
def mnemonic_int(operands, errors=None):
    opcode = None
    opcode_operands = bytearray()

    if validate_operands_count(operands, 1, errors):
        operand = operands[0].lower()
        if data.is_valid_str(operand) or data.is_valid_chr(operand):
            if errors is not None:
                errors.append({
                    'name': 'UNSUPPORTED_OPERAND',
                    'info': [operand]
                })
        elif validate_operand_data_size(operand, 8, errors):
            # call interrupt is supported with max. 8-bit data with a value up to 63 (for 64 interrupts)
            opcode = 0b11011111
            data_value = data.get_value(operand)
            if data_value > 63:
                if errors is not None:
                    errors.append({
                        'name': 'INVALID_INT',
                        'info': [data_value]
                    })
            else:
                opcode_operands.append(data_value)

    if errors:
        return None
    else:
        machine_code = bytearray()
        machine_code.append(opcode)
        machine_code.extend(opcode_operands)
        return {'machine_code': machine_code, 'relocation_table': []}
Ejemplo n.º 2
0
Archivo: rom.py Proyecto: wrzlbrmft/cpu
def read_flags_file(file_name, errors=None):
    global current_file_name, current_line_num, current_line_str

    if os.path.isfile(file_name):
        flags = {}
        flags_bits = 0

        with open(file_name, 'r') as file:
            current_file_name = file_name
            line_num = 0
            current_line_num = line_num

            for line_str in file.readlines():
                current_line_str = line_str
                line_num += 1
                current_line_num = line_num

                line_str = line_str.strip()
                if line_str:
                    i = line_str.split(';')

                    flag_name = i[0].strip()
                    if is_valid_name(flag_name):
                        if len(i) > 1:
                            flag_value = i[1].strip()
                            if data.is_valid(
                                    flag_value
                            ) and not data.is_valid_str(flag_value):
                                flag_value = data.get_value(flag_value)
                            else:
                                if errors is not None:
                                    errors.append({
                                        'name': 'INVALID_FLAG_VALUE',
                                        'info': [flag_value]
                                    })
                                return None, None
                        else:
                            flag_value = int(math.pow(2, flags_bits))

                        flags[flag_name] = flag_value
                        flags_bits = max(flags_bits, flag_value.bit_length())
                    else:
                        if errors is not None:
                            errors.append({
                                'name': 'INVALID_FLAG_NAME',
                                'info': [flag_name]
                            })
                        return None, None

        return flags, flags_bits
    else:
        if errors is not None:
            errors.append({'name': 'FILE_NOT_FOUND', 'info': [file_name]})
        return None, None
Ejemplo n.º 3
0
def mnemonics_add_sub_cmp_adc_sbb_and_or_xor(mnemonic, operands, errors=None):
    opcode = None
    opcode_operands = bytearray()

    if validate_operands_count(operands, 1, errors):
        # add (with carry), subtract (with borrow), compare, and, or and xor are supported with M, any 8-bit register or
        # max. 8-bit data or a single character but no string
        operand = operands[0].lower()
        if 'm' == operand:
            opcode = 0b110
        elif is_valid_register(operand):
            if validate_operand_register_size(operand, 8, errors):
                register_opcode = get_register_opcode(operand)
                opcode = register_opcode
        elif data.is_valid_str(operand):
            if errors is not None:
                errors.append({'name': 'INCOMPATIBLE_DATA_TYPE', 'info': []})
        elif validate_operand_data_size(operand, 8, errors):
            opcode = 0b111
            data_value = data.get_value(operand)
            opcode_operands.append(data_value)

        if opcode is not None:
            if 'add' == mnemonic:
                opcode = 0b01100000 | (opcode << 1)
            elif 'sub' == mnemonic:
                opcode = 0b01100001 | (opcode << 1)
            elif 'cmp' == mnemonic:
                opcode = 0b01110000 | (opcode << 1)
            elif 'adc' == mnemonic:
                opcode = 0b01010000 | opcode
            elif 'sbb' == mnemonic:
                opcode = 0b01011000 | opcode
            elif 'and' == mnemonic:
                opcode = 0b00110000 | opcode
            elif 'or' == mnemonic:
                opcode = 0b00111000 | opcode
            elif 'xor' == mnemonic:
                opcode = 0b01000000 | opcode

    if errors:
        return None
    else:
        machine_code = bytearray()
        machine_code.append(opcode)
        machine_code.extend(opcode_operands)
        return {'machine_code': machine_code, 'relocation_table': []}
Ejemplo n.º 4
0
def mnemonics_db_dw(mnemonic, operands, errors=None):
    opcode_operands = bytearray()
    _relocation_table = []

    if operands:
        for operand in operands:
            operand_splits = operand.rsplit(None, 3)
            if len(operand_splits) == 4 and '(' == operand_splits[
                    -3] and ')' == operand_splits[-1]:
                operand = operand_splits[0]
                multiplier = operand_splits[-2]
                if data.is_valid_str(multiplier) or data.is_valid_chr(
                        multiplier):
                    if errors is not None:
                        errors.append({
                            'name': 'UNSUPPORTED_MULTIPLIER',
                            'info': [multiplier]
                        })
                    opcode_operands.clear()
                    break
                elif data.get_size(multiplier) is None or data.get_value(
                        multiplier) < 1:
                    if errors is not None:
                        errors.append({
                            'name': 'INVALID_MULTIPLIER',
                            'info': [multiplier]
                        })
                    opcode_operands.clear()
                    break
                elif data.get_size(multiplier) > 16:
                    if errors is not None:
                        errors.append({
                            'name': 'UNSUPPORTED_MULTIPLIER_SIZE',
                            'info': [data.get_size(multiplier), 16]
                        })
                    opcode_operands.clear()
                    break
                multiplier_value = data.get_value(multiplier)
            else:
                multiplier_value = 1

            if 'db' == mnemonic:
                # bytes support max. 8-bit data, a single character or a string
                if validate_operand_data_size(operand, 8, errors):
                    if data.is_valid_str(operand):
                        data_values = data.get_value(
                            operand) * multiplier_value
                        opcode_operands.extend(data_values)
                    else:
                        data_value = data.get_value(operand)
                        opcode_operands.extend([data_value] * multiplier_value)
                else:
                    opcode_operands.clear()
                    break
            elif 'dw' == mnemonic:
                # words support a symbol name (using relocation), max. 16-bit data, a single character or a string both
                # including unicode
                if is_valid_name(operand):
                    operand = expand_local_symbol_name(operand)
                    opcode_operands.extend([0, 0])
                    _relocation_table.append({
                        'machine_code_offset':
                        len(opcode_operands) - 2,
                        'symbol_index':
                        symbol_table.get_index(operand)
                    })
                elif validate_operand_data_size(operand, 16, errors):
                    if data.is_valid_str(operand):
                        data_values = data.get_value(
                            operand) * multiplier_value
                        for data_value in data_values:
                            opcode_operands.extend(
                                binutils.word_to_le(data_value))
                    else:
                        data_value = data.get_value(operand)
                        opcode_operands.extend(
                            binutils.word_to_le(data_value) * multiplier_value)
                else:
                    opcode_operands.clear()
                    break
    else:
        if errors is not None:
            errors.append({'name': 'NO_DATA', 'info': []})

    if errors:
        return None
    else:
        machine_code = bytearray()
        machine_code.extend(opcode_operands)
        return {
            'machine_code': machine_code,
            'relocation_table': _relocation_table
        }
Ejemplo n.º 5
0
def mnemonic_mov(operands, errors=None):
    opcode = None
    opcode_operands = bytearray()
    _relocation_table = []

    if validate_operands_count(operands, 2, errors):
        operand1 = operands[0].lower()
        operand2 = operands[1].lower()
        if 'm' == operand1:
            # move into M is only supported from an 8-bit register
            register1_opcode = 0b110
            if validate_operand_register_size(operand2, 8, errors):
                register2_opcode = get_register_opcode(operand2)
                opcode = 0b10000000 | (register1_opcode << 4) | (
                    register2_opcode << 1)
        elif validate_operand_register(operand1, errors):
            register1_size = get_register_size(operand1)
            register1_opcode = get_register_opcode(operand1)
            if 8 == register1_size:
                # move into an 8-bit register is supported from M, another 8-bit register or using max. 8-bit data or a
                # single character but no string
                register2_opcode = None
                if 'm' == operand2:
                    register2_opcode = 0b110
                elif is_valid_register(operand2):
                    if validate_operand_register_size(operand2, register1_size,
                                                      errors):
                        register2_opcode = get_register_opcode(operand2)
                elif data.is_valid_str(operand2):
                    if errors is not None:
                        errors.append({
                            'name': 'INCOMPATIBLE_DATA_TYPE',
                            'info': []
                        })
                elif validate_operand_data_size(operand2, register1_size,
                                                errors):
                    register2_opcode = 0b111
                    data_value = data.get_value(operand2)
                    opcode_operands.append(data_value)

                if register2_opcode is not None:
                    opcode = 0b10000000 | (register1_opcode << 4) | (
                        register2_opcode << 1)
            elif 16 == register1_size:
                # move into a 16-bit register is supported from a symbol name (using relocation), another 16-bit
                # register or using max. 16-bit data or a single character including unicode but no string
                register2_opcode = None
                if is_valid_name(operand2):
                    operand2 = expand_local_symbol_name(operand2)
                    register2_opcode = 0b111
                    opcode_operands.extend([0, 0])
                    _relocation_table.append({
                        'machine_code_offset':
                        1,
                        'symbol_index':
                        symbol_table.get_index(operand2)
                    })
                elif is_valid_register(operand2):
                    if validate_operand_register_size(operand2, register1_size,
                                                      errors):
                        register2_opcode = get_register_opcode(operand2)
                elif data.is_valid_str(operand2):
                    errors.append({
                        'name': 'INCOMPATIBLE_DATA_TYPE',
                        'info': []
                    })
                elif validate_operand_data_size(operand2, register1_size,
                                                errors):
                    register2_opcode = 0b111
                    data_value = data.get_value(operand2)
                    opcode_operands.extend(binutils.word_to_le(data_value))

                if register2_opcode is not None:
                    opcode = (register1_opcode << 4) | (register2_opcode << 1)

    if errors:
        return None
    else:
        machine_code = bytearray()
        machine_code.append(opcode)
        machine_code.extend(opcode_operands)
        return {
            'machine_code': machine_code,
            'relocation_table': _relocation_table
        }
Ejemplo n.º 6
0
def is_valid_addr(s):
    # a symbol name is always a valid address (the linker will determine the address during relocation)
    return is_valid_name(s) or (data.is_valid(s) and not data.is_valid_chr(s)
                                and not data.is_valid_str(s))
Ejemplo n.º 7
0
Archivo: rom.py Proyecto: wrzlbrmft/cpu
def parse_csv_line(line_str, errors=None):
    columns = line_str.split(';')

    addr_value = ''
    data_value = ''

    for column, bits in addr_config.items():
        if column <= len(columns):
            column_value = columns[column - 1].strip()
            if data.is_valid(
                    column_value) and not data.is_valid_str(column_value):
                column_value = format(data.get_value(column_value), 'b')
                if bits is not None:
                    column_value = column_value.zfill(bits)
            elif is_valid_bits(column_value):
                column_value = get_bits_value(column_value)
                if bits is not None:
                    column_value = column_value.zfill(bits)
            else:
                if errors is not None:
                    errors.append({
                        'name': 'INVALID_ADDR_VALUE',
                        'info': [column_value]
                    })
                return None, None
            addr_value += column_value
        else:
            if errors is not None:
                errors.append({
                    'name': 'ADDR_COLUMN_NOT_FOUND',
                    'info': [column]
                })
                return None, None

    if addr_config_bits is not None and len(addr_value) > addr_config_bits:
        if errors is not None:
            errors.append({
                'name': 'INCOMPATIBLE_ADDR_SIZE',
                'info': [len(addr_value), addr_config_bits]
            })
            return None, None

    if data_config_column <= len(columns):
        column_value = columns[data_config_column - 1].strip()
        if data.is_valid(column_value) and not data.is_valid_str(column_value):
            column_value = format(data.get_value(column_value), 'b')
            if data_config_bits is not None:
                column_value = column_value.zfill(data_config_bits)
        elif data_config_flags:
            flag_names = column_value.split(',')
            column_value = 0
            for flag_name in flag_names:
                flag_name = flag_name.strip()
                if flag_exists(flag_name):
                    column_value |= get_flag_value(flag_name)
                else:
                    if errors is not None:
                        errors.append({
                            'name': 'UNKNOWN_FLAG',
                            'info': [flag_name]
                        })
                    return None, None
            column_value = format(column_value, 'b').zfill(data_config_bits)
        else:
            if errors is not None:
                errors.append({
                    'name': 'INVALID_DATA_VALUE',
                    'info': [column_value]
                })
            return None, None
        data_value = column_value
    else:
        if errors is not None:
            errors.append({
                'name': 'DATA_COLUMN_NOT_FOUND',
                'info': [data_config_column]
            })
            return None, None

    if data_config_bits is not None and len(data_value) > data_config_bits:
        if errors is not None:
            errors.append({
                'name': 'INCOMPATIBLE_DATA_SIZE',
                'info': [len(data_value), data_config_bits]
            })
            return None, None

    return addr_value, data_value
Ejemplo n.º 8
0
def parse_zero_fill(zero_fill_str):
    if data.is_valid(zero_fill_str) and not data.is_valid_str(zero_fill_str):
        return data.get_value(zero_fill_str)
    else:
        show_error({'name': 'INVALID_ZERO_FILL', 'info': [zero_fill_str]})
        return None