Exemplo n.º 1
0
def check_psrtransop(name, operands):
    """
    Assumes valid name, valid name+flags combination, valid condcode.
    Check the operands and return an error string if invalid, empty string otherwise.
    """
    operands = [x.strip() for x in operands.split(',')]
    if len(operands) != 2:
        return 'Invalid number of operands: expected 2, got %i' % (len(operands))
    if name == 'MRS':
        if not helpers.is_reg(operands[0]):
            return 'Invalid operand: expected register'
        rd = helpers.get_reg_num(operands[0])
        if rd == 15:
            return 'PC is not allowed here'
        if not operands[1].upper() in ['SPSR', 'SPSR_ALL', 'CPSR', 'CPSR_ALL']:
            return 'Invalid operand: expected psr'
        return ''
    else:
        if not helpers.is_psr(operands[0]):
            return 'Invalid operand: expected psr'
        if not operands[0].upper().endswith('FLG'):
            if not helpers.is_reg(operands[1]):  # immediate is only allowed for PSR_FLG
                return 'Invalid operand: expected register'
            if helpers.get_reg_num(operands[1]) == 15:
                return 'PC is not allowed here'
            return ''
        if helpers.is_reg(operands[1]):
            if helpers.get_reg_num(operands[1]) == 15:
                return 'PC is not allowed here'
            return ''
        if not helpers.is_valid_imval(operands[1]):
            return 'Invalid operand: expected register or immediate value'
        if not helpers.is_expressable_imval(operands[1]):
            return 'This immediate value cannot be encoded'
        return ''
Exemplo n.º 2
0
def check_op2(op2):
    """
    Check Op2 of a dataprocop.
    Return an error string if invalid, empty string otherwise.
    """
    operands = [x.strip() for x in op2.split(',')]
    if len(operands) == 1:
        if helpers.is_reg(operands[0]):  # op2 = reg
            return ''
        if not helpers.is_valid_imval(operands[0]):  # op2 = immediate
            return 'Invalid op2 (must be of the form "reg" or "reg, shift" or "immediate value")'
        # constant must be expressable as "8bit unsigned int" rotated right by 2*n with n an "4 bit unsigned int"
        if not helpers.is_expressable_imval(operands[0]):
            return 'This immediate value cannot be encoded as op2'
        return ''
    if len(operands) != 2:
        return 'Invalid op2 (must be of the form "reg" or "reg, shift" or "immediate value")'
    # ->must be of form "reg, shift"
    if not helpers.is_reg(operands[0]):
        return 'Invalid op2 (must be of the form "reg" or "reg, shift" or "immediate value")'
    if '#' in operands[1]:
        operands[1] = operands[1][:operands[1].find(
            '#'
        )] + ' ' + operands[1][operands[1].find(
            '#'
        ):]  # make it legal to omit the space between shiftname and immediate value
    shift = [x.strip() for x in operands[1].split()]
    if len(shift) == 1:  # "RRX" or "shiftname reg" or "shiftname immediate"
        if shift[0] != 'RRX':
            return 'Invalid op2 (must be of the form "reg" or "reg, shift" or "immediate value")'
        return ''
    elif len(shift) > 2:
        return 'Invalid op2 (must be of the form "reg" or "reg, shift" or "immediate value")'
    if not helpers.is_shiftname(shift[0]):
        return 'Invalid op2 (must be of the form "reg" or "reg, shift" or "immediate value")'
    if helpers.is_reg(shift[1]):
        if helpers.get_reg_num(shift[1]) == 15:
            return 'PC may not be used here'
        return ''
    if not helpers.is_valid_imval(shift[1]):
        return 'Invalid op2 (must be of the form "reg" or "reg, shift" or "immediate value")'
    amount = helpers.imval_to_int(shift[1])
    if amount >= 0 and amount <= 31:
        return ''
    elif amount == 32 and shift[0] not in ['LSR', 'ASR']:
        return 'Shift by 32 is only allowed for LSR'
    return 'Invalid immediate shift amount. Must be 0 <= amount <= 31 (or 32 for special LSR, ASR)'
Exemplo n.º 3
0
def check_swiop(name, operands):
    """
    Assumes valid name, valid name+flags combination, valid condcode.
    Check the operands and return an error string if invalid, empty string otherwise.
    """
    operands = [x.strip() for x in operands.split(',')]
    if len(operands) != 1:
        return 'Invalid number of operands: expected 1, got %i' % (len(operands))
    operands = operands[0]
    if not helpers.is_valid_imval(operands):
        return 'Invalid operand: expected immediate value'
    com = helpers.imval_to_int(operands)
    if com > 2**24-1:
        return 'Operand greater than 2^24-1'
    if com < -2**23:
        return 'Operand lower than -2^23'
    return ''
Exemplo n.º 4
0
def is_valid_addresspart(hsflag, addresspart, tflag, address, labeldict):
    """
    hsflag = True -> selects syntax checking for halfword or signed data transfer instructions, False selects normal unsigned word/byte transfer syntax.
    Address must be the address of this instruction.
    Return empty string if addresspart is valid according to the syntax rules for datatransfer address part, error string otherwise.
    """
    if len(addresspart) < 1:
        return 'Address part is missing'
    if addresspart[
            0] != '[':  # must be an expression (label) if not starting with a bracket
        if addresspart not in labeldict:
            return 'Expected bracket or label'
        offset = labeldict[addresspart] - address - 8
        addresspart = '[PC, #' + str(offset) + ']'  # range check done below
    writeback = False
    if addresspart[-1] == '!':
        writeback = True
        addresspart = addresspart[:-1].strip()  # strip the trailing !
    if addresspart[-1] == ']':
        preindexed = True
        addresspart = addresspart[:-1].strip()  # strip the trailing ]
    else:
        if writeback:
            return '! is only allowed for preindexed addressing'
        preindexed = False
    addresspart = addresspart[1:].strip()  # strip the leading [
    addresspart = [x.strip() for x in addresspart.split(',')]
    if len(addresspart) < 1 or len(addresspart) > 3 or (hsflag and
                                                        len(addresspart) > 2):
        return 'Invalid addresspart'
    if not preindexed:
        if addresspart[0][-1:] != ']':
            return 'Expected closing ]'
        addresspart[0] = addresspart[0][:-1].strip()  # strip the trailing ]
    # there should be no syntax differences between pre- and post-indexing left
    if not helpers.is_reg(addresspart[0]):
        return 'Expected register as base'
    if writeback and helpers.get_reg_num(addresspart[0]) == 15:
        return 'Write-back should not be used when PC is the base register'
    if preindexed and tflag:
        return 'T-flag is not allowed when pre-indexing is used'
    if len(addresspart) == 1:
        return ''
    if helpers.is_valid_imval(addresspart[1]):
        n = helpers.imval_to_int(addresspart[1])
        if hsflag:
            limit = 2**8 - 1
        else:
            limit = 2**12 - 1
        if n > limit:
            return 'Offset too high (max. %i)' % (limit)
        if n < -limit:
            return 'Offset too low (min. %i)' % (-limit)
        if len(addresspart) > 2:
            return 'Too many operands'
        return ''
    else:
        if len(addresspart[1]) < 2:
            return 'Invalid offset'
        if addresspart[1][0] in ['+', '-']:
            addresspart[1] = addresspart[1][1:]
        if not helpers.is_reg(addresspart[1]):
            return 'Invalid offset: must be register or immediate value'
        if helpers.get_reg_num(addresspart[1]) == 15:
            return 'PC is not allowed as offset'
        if not preindexed and helpers.get_reg_num(
                addresspart[0]) == helpers.get_reg_num(addresspart[1]):
            return 'Manual says: post-indexed with Rm = Rn should not be used'
        if len(addresspart) == 2:
            return ''
        if hsflag:
            return 'Expected less operands'
        # addresspart[2] should be a shift:
        if len(addresspart[2]) < 3:
            return 'Invalid shift expression'
        shift = addresspart[2]
        if shift.upper() == 'RRX':
            return ''
        shift = shift.split()
        if len(shift) == 1 and '#' in shift[0]:
            shift = shift[0].split('#')
            shift[1] = '#' + shift[1]
        if len(shift) != 2:
            return 'Invalid shift expression'
        if not helpers.is_shiftname(shift[0]):
            return 'Invalid shift name'
        if helpers.is_reg(shift[1]):
            return 'Register specified shift amount is not allowed in data transfer instructions'
        if not helpers.is_valid_imval(shift[1]):
            return 'Invalid shift amount'
        n = helpers.imval_to_int(shift[1])
        if n >= 0 and n <= 31:
            return ''
        elif n == 32 and shift[0] not in ['LSR', 'ASR']:
            return 'Shift by 32 is only allowed for LSR'
        return 'Invalid immediate shift amount. Must be 0 <= amount <= 31 (or 32 for special LSR, ASR)'
Exemplo n.º 5
0
def parse_datatrans(name, operands, address, labeldict):
    """
    check_singledatatransop or check_halfsigneddatatransop must be called before this.
    Does the stuff common to halfsigned and normal datatrans encoding.
    """
    if operands.count('[') == 0:
        label = operands.split(',')[1].strip()
        offset = labeldict[label] - address - 8
        operands = operands.split(',')[0] + ',[PC, #' + str(offset) + ']'
    writeback = (operands[-1] == '!')
    if writeback:
        operands = operands[:-1].strip()
    preindexed = (operands[-1] == ']')
    if preindexed:
        operands = operands[:-1].strip()
    loadflag = (name == 'LDR')
    operands = [x.strip() for x in operands.split(',')]
    operands[1] = operands[1][1:].strip()
    if operands[1][-1] == ']':
        operands[1] = operands[1][:-1].strip()
    rd = helpers.get_reg_num(operands[0])
    rn = helpers.get_reg_num(operands[1])
    offset = 0
    upflag = True
    iflag = False
    if len(operands) > 2:
        if helpers.is_valid_imval(operands[2]):
            iflag = False  # !!!
            offset = helpers.imval_to_int(operands[2])
            upflag = (offset >= 0)
            offset = abs(offset)
        else:
            iflag = True
            upflag = True
            if operands[2][0] == '-':
                upflag = False
                operands[2] = operands[2][1:]
            elif operands[2][0] == '+':
                operands[2] = operands[2][1:]
            rm = helpers.get_reg_num(operands[2])
            shiftfield = 0
            if len(operands) == 4:
                shift = [x.strip() for x in operands[3].split()]
                if len(shift) == 1:  # RRX
                    shifttype = 'ROR'
                    shiftby = 0
                else:
                    shifttype = shift[0]
                    shiftby = helpers.imval_to_int(shift[1])
                    if shiftby == 0:
                        shifttype = 'LSL'
                    if shifttype.upper() in ['LSR', 'ASR'] and shiftby == 32:
                        shiftby = 0
                shiftfield = (shiftby << 3) | {
                    'LSL': 0,
                    'ASL': 0,
                    'LSR': 1,
                    'ASR': 2,
                    'ROR': 3
                }[shifttype.upper()] << 1
            offset = (shiftfield << 4) | rm
    return (writeback, preindexed, loadflag, upflag, iflag, rd, rn, offset)