コード例 #1
0
ファイル: operations.py プロジェクト: alexsocha/mipsplusplus
def binaryOperation(operation, reg1, reg2, outputReg, props):
  resultLines = []
  standardComment = utils.formatComment('{} = {} {} {}'.format(outputReg, reg1, operation, reg2), props, 2)
  operationComment = utils.formatComment('{} {} {}'.format(reg1, '/' if operation == '%' else operation, reg2), props, 2)

  if reg1 == '0': reg1 = '$0'
  if reg2 == '0': reg2 = '$0'
  reg1 = utils.getRegister(reg1)
  reg2 = utils.getRegister(reg2)

  didChangeReg1 = False
  if (not operation in BIN_OPERATORS_IMM and utils.isIntOrChar(reg1)) or (utils.isIntOrChar(reg1) and utils.isIntOrChar(reg2)):
    tempReg = utils.getTempRegister(props['tempRegisters'], 0)
    resultLines.append(general.loadIntOrChar(reg1, tempReg, props))
    reg1 = tempReg
    didChangeReg1 = True
  if not operation in BIN_OPERATORS_IMM and utils.isIntOrChar(reg2):
    tempReg = utils.getTempRegister(props['tempRegisters'], 1 if didChangeReg1 else 0)
    resultLines.append(general.loadIntOrChar(reg2, tempReg, props))
    reg2 = tempReg

  # Using 2 registers
  if utils.isRegister(reg1) and utils.isRegister(reg2):
    if operation in BIN_RESULT_REGS:
      # Move from hi/lo
      resultLines.append('{} {}, {}{}'.format(BIN_OPERATORS[operation], reg1, reg2, operationComment))
      resultLines.append(general.loadRegHiLo(BIN_RESULT_REGS[operation], outputReg, {**props, 'comment': standardComment}))
    else:
      resultLines.append('{} {}, {}, {}{}'.format(BIN_OPERATORS[operation], utils.getRegister(outputReg), reg1, reg2, standardComment))
  else:
    # Immediate
    regNum, number = (reg1, utils.getIntOrChar(reg2)) if utils.isRegister(reg1) else (reg2, utils.getIntOrChar(reg1))
    resultLines.append('{} {}, {}, {}{}'.format(BIN_OPERATORS_IMM[operation], utils.getRegister(outputReg), regNum, number, standardComment))

  return { 'lines': resultLines, 'reg': outputReg }
コード例 #2
0
ファイル: operations.py プロジェクト: alexsocha/mipsplusplus
def unaryOperation(operation, reg1, outputReg, props):
  resultLines = []

  if utils.isIntOrChar(reg1):
    tempReg = utils.getTempRegister(props['tempRegisters'], 0)
    resultLines.append(general.loadIntOrChar(reg1, tempReg, props))
    reg1 = tempReg

  comment = utils.formatComment('{} = {} {}'.format(outputReg, operation, reg1), props, 2)
  resultLines.append('{} {}, {}{}'.format(UN_OPERATORS[operation], utils.getRegister(outputReg), utils.getRegister(reg1), comment))
  return { 'lines': resultLines, 'reg': outputReg }
コード例 #3
0
def parseSingleRHS(expression,
                   props,
                   outputReg,
                   inferredType='any',
                   loadAsAddress=False):
    resultLines = []
    resultAddr = None
    resultType = inferredType

    if loadAsAddress and (utils.isRegister(expression)
                          or utils.isSysFunc(expression)):
        raise utils.CompileException('Can\'t get address of register')

    # System functions
    if utils.isSysFunc(expression):
        resultLines += functions.parseSysFunc(expression, props, True)
        resultType = definitions.updateType(resultType, 'number')
        if outputReg != '$v0':
            resultLines.append(general.loadRegister('$v0', outputReg, props))

    # Array
    elif addresses.isArray(expression):
        parsedAddr = addresses.parseArray(expression, props, outputReg)
        outerInner = (parsedAddr['outer'], parsedAddr['inner'])
        resultLines += parsedAddr['lines']

        if loadAsAddress:
            resultType = definitions.updateType('address', resultType)
            if parsedAddr['reg'] != outputReg:
                resultLines.append(
                    general.loadAsAddress(parsedAddr['address'], outputReg,
                                          props, outerInner))
            if parsedAddr['reg'] == None: resultAddr = parsedAddr['address']
        else:
            loadType = definitions.updateType(resultType,
                                              parsedAddr['elemtype'])
            resultLines.append(
                general.loadFromAddress(parsedAddr['address'], loadType,
                                        outputReg, props, outerInner))
            resultType = definitions.updateType(loadType, resultType)

    # Register
    elif utils.isRegister(expression):
        if general.isRegHiLo(expression):
            resultLines.append(
                general.loadRegHiLo(expression, outputReg, props))
        elif utils.getRegister(expression) != utils.getRegister(outputReg):
            resultLines.append(
                general.loadRegister(expression, outputReg, props))

    # Variable
    elif expression in props['variables']:
        varName, varType = props['variables'][expression]['name'], props[
            'variables'][expression]['type']
        if definitions.getSupertype(varType) == 'address' or loadAsAddress:
            resultLines.append(general.loadAsAddress(varName, outputReg,
                                                     props))
            resultType = definitions.updateType(varType, resultType)
            resultAddr = varName
        else:
            resultLines.append(
                general.loadFromAddress(varName, varType, outputReg, props))
            resultType = definitions.updateType(varType, resultType)

    # Integer or char literal
    elif utils.isIntOrChar(expression):
        resultType = definitions.updateType(
            resultType, 'char' if utils.isChar(expression) else 'number')
        resultLines.append(general.loadIntOrChar(expression, outputReg, props))

    # Address
    elif addresses.isAddress(expression, props):
        resultType = definitions.updateType('address', resultType)
        if definitions.getSupertype(resultType) == 'address':
            resultLines.append(
                general.loadAsAddress(expression, outputReg, props))
        else:
            resultLines.append(
                general.loadFromAddress(expression, resultType, outputReg,
                                        props))
        resultAddr = expression

    return {
        'lines': resultLines,
        'type': resultType,
        'reg': outputReg,
        'address': resultAddr
    }
コード例 #4
0
def parseRHS(expression, props, outputReg='any', inferredType='any'):
    # Convert the expression to postfix (RPN) notation
    splitExp = parser.infixToPostfix(parser.splitExpression(expression))

    allTempRegs = props['tempRegisters']
    resultLines = []
    resultAddr = None

    # Parse the expression as a stack of operations
    equationStack = []
    typeStack = []
    asAddressStack = []
    availableTempRegIdx = 0
    for i, item in enumerate(splitExp):
        val1, val2 = item, None
        val1Type, val2Type = inferredType, inferredType
        val1AsAddress, val2AsAddress = False, False
        val1Addr, val2Addr = None, None  # Haven't optimized address addition yet
        reg1, reg2 = None, None
        limitedProps = utils.propsWithTempRegOffset(props, availableTempRegIdx)

        finalIteration = i == len(splitExp) - 1 or (
            i == len(splitExp) - 3 and
            (splitExp[-1] == 'as' or splitExp[-1] == 'addressof'))
        targetReg = utils.getTempRegister(limitedProps['tempRegisters'], 0)
        if finalIteration:
            if utils.isSysFunc(item) and outputReg == 'any': targetReg = '$v0'
            elif outputReg == 'any':
                targetReg = utils.getTempRegister(allTempRegs, 0)
            else:
                targetReg = outputReg

        prevTempReg = None if availableTempRegIdx < 1 else utils.getTempRegister(
            allTempRegs, availableTempRegIdx - 1)
        prevPrevTempReg = None if availableTempRegIdx < 2 else utils.getTempRegister(
            allTempRegs, availableTempRegIdx - 2)

        if item in operations.BIN_OPERATORS or item == 'as':
            val1, val2 = equationStack[-2], equationStack[-1]
            val1Type, val2Type = typeStack[-2], typeStack[-1]
            val1AsAddress, val2AsAddress = asAddressStack[-2], asAddressStack[
                -1]
        elif item in operations.UN_OPERATORS or item == 'addressof':
            val1, val1Type, val1AsAddress = equationStack[-1], typeStack[
                -1], asAddressStack[-1]

        # Special operators
        if item == 'as':
            equationStack.pop()
            asAddressStack.pop()
            typeStack.pop()
            typeStack.pop()
            typeStack.append(val2)
            val1, val1Type, val1AsAddress = equationStack[-1], typeStack[
                -1], asAddressStack[-1]
        elif item == 'addressof':
            asAddressStack.pop()
            asAddressStack.append(True)
            val1, val1Type, val1AsAddress = equationStack[-1], typeStack[
                -1], asAddressStack[-1]
        else:
            # Get first register
            if item in operations.BIN_OPERATORS or item in operations.UN_OPERATORS:
                if utils.isIntOrChar(val1): reg1 = val1
                else:
                    if utils.isRegister(val1): reg1 = val1
                    else: reg1 = targetReg
                    parsed = parseSingleRHS(val1, limitedProps, reg1, val1Type,
                                            val1AsAddress)
                    resultLines += parsed['lines']
                    val1Type, val1Addr = parsed['type'], parsed['address']
                    if not utils.isRegister(val1):
                        limitedProps = utils.propsWithTempRegOffset(
                            limitedProps, 1)

            # Get Second register
            if item in operations.BIN_OPERATORS:
                if utils.isIntOrChar(val2): reg2 = val2
                else:
                    if utils.isRegister(val2): reg2 = val2
                    elif reg1 == targetReg:
                        reg2 = utils.getTempRegister(
                            limitedProps['tempRegisters'], 0)
                    else:
                        reg2 = targetReg
                    parsed = parseSingleRHS(val2, limitedProps, reg2, val2Type,
                                            val2AsAddress)
                    resultLines += parsed['lines']
                    val2Type, val2Addr = parsed['type'], parsed['address']
                    if not utils.isRegister(val2):
                        limitedProps = utils.propsWithTempRegOffset(
                            limitedProps, 1)

        # Do binary operation
        if item in operations.BIN_OPERATORS:
            # Try to re-use/free-up temporary registers where possible
            equationReg = targetReg
            if utils.isTempRegister(equationReg, allTempRegs):
                if val1 == prevPrevTempReg: equationReg = val1
                elif val2 == prevTempReg: equationReg = val2
                else: availableTempRegIdx += 1
                if val1 == prevPrevTempReg and val2 == prevTempReg:
                    # Suggested Optimization: Even though it frees up a register, it doesn't
                    # keep track of the value inside it. This could potentially prevent
                    # the same value from being re-loaded.
                    availableTempRegIdx -= 1

            # Parse the operation
            parsedOperation = operations.binaryOperation(
                item, reg1, reg2, equationReg, limitedProps)
            resultLines += parsedOperation['lines']
            equationStack.pop()
            equationStack.pop()
            typeStack.pop()
            typeStack.pop()
            asAddressStack.pop()
            asAddressStack.pop()
            equationStack.append(parsedOperation['reg'])
            typeStack.append(definitions.mergeType(val1Type, val2Type))
            asAddressStack.append(False)

        # Do unary operation
        elif item in operations.UN_OPERATORS:
            # Try to re-use/free-up temporary registers where possible
            equationReg = targetReg
            if utils.isTempRegister(equationReg, allTempRegs):
                if val1 == prevTempReg: equationReg = val1
                else: availableTempRegIdx += 1

            # Parse the operation
            parsedOperation = operations.unaryOperation(
                item, reg1, equationReg, limitedProps)
            resultLines += parsedOperation['lines']
            equationStack.pop()
            typeStack.pop()
            asAddressStack.pop()
            equationStack.append(parsedOperation['reg'])
            typeStack.append(val1Type)
            asAddressStack.append(False)

        # Handle expressions without operators
        elif i == len(splitExp) - 1:
            if outputReg == 'any':
                if val1 == '0': val1 = '$0'
                if utils.isRegister(val1): targetReg = val1
            parsed = parseSingleRHS(val1, limitedProps, targetReg, val1Type,
                                    val1AsAddress)
            resultLines += parsed['lines']
            val1Type, val1Addr = parsed['type'], parsed['address']
            resultAddr = val1Addr
            equationStack.append(targetReg)
            typeStack.append(val1Type)
            asAddressStack.append(False)

        # Add to stack
        elif item != 'as' and item != 'of':
            equationStack.append(item)
            if utils.isInt(item): typeStack.append('number')
            elif utils.isChar(item): typeStack.append('char')
            else: typeStack.append('any')
            asAddressStack.append(False)

    return {
        'lines': resultLines,
        'type': typeStack[-1],
        'reg': equationStack[-1],
        'address': resultAddr
    }
コード例 #5
0
def parseArray(expression, props, addressReg='any'):
    resultLines = []
    resultReg = None
    resultType = 'address'
    elemType = 'any'
    resultAddress = 'none'
    outer, inner = None, None

    outerAddr = expression[:expression.index('[')]
    innerExpr = expression[expression.index('[') + 1:-1].strip()

    if outerAddr in props['variables'] and 'elemtype' in props['variables'][
            outerAddr]:
        resultType = definitions.updateType(
            props['variables'][outerAddr]['type'], 'address')
        if 'elemtype' in props['variables'][outerAddr]:
            elemType = props['variables'][outerAddr]['elemtype']

    # Optimize offset literals
    if utils.isIntOrChar(innerExpr):
        value = utils.getIntOrChar(innerExpr)
        if utils.isRegister(outerAddr):
            if value == 0:
                resultAddress = '({})'.format(utils.getRegister(outerAddr))
            else:
                resultAddress = '{}({})'.format(value,
                                                utils.getRegister(outerAddr))
        else:
            if value == 0: resultAddress = outerAddr
            else: resultAddress = '{}+{}'.format(outerAddr, value)
        outer, inner = outerAddr, value
    else:
        # Parse inner expression
        exprReg = None
        if utils.isRegister(innerExpr): exprReg = innerExpr
        else:
            parsedExpr = expressions.parseRHS(innerExpr, props, 'any',
                                              'number')
            resultLines += parsedExpr['lines']
            exprReg = parsedExpr['reg']

        limitedProps = utils.propsWithTempRegExcl(props, [exprReg])
        resultReg = addressReg
        if resultReg is 'any' or resultReg == exprReg:
            resultReg = utils.getTempRegister(limitedProps['tempRegisters'], 0)

        newAddress = outerAddr
        if utils.isRegister(outerAddr):
            newAddress = '({})'.format(utils.getRegister(outerAddr))
        resultLines.append(
            general.loadAsAddress(newAddress, resultReg, props,
                                  (outerAddr, '0')))
        addOperation = operations.binaryOperation('+', resultReg, exprReg,
                                                  resultReg, limitedProps)

        resultLines += addOperation['lines']
        resultAddress = '({})'.format(utils.getRegister(resultReg))
        outer, inner = resultReg, '0'

    return {
        'lines': resultLines,
        'type': resultType,
        'elemtype': elemType,
        'reg': resultReg,
        'address': resultAddress,
        'outer': outer,
        'inner': inner
    }