Beispiel #1
0
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 }
Beispiel #2
0
def loadFromAddress(address, loadType, outputReg, props, outerInner=None):
    numLoadFuncs = {
        'int': 'lw',
        'short': 'lh',
        'byte': 'lb',
        'char': 'lb',
        'number': 'lw',
        'address': 'lw'
    }
    loadFunc = 'lw'
    if definitions.getSupertype(loadType) == 'address': loadType = 'address'
    if loadType in numLoadFuncs: loadFunc = numLoadFuncs[loadType]
    if utils.isRegister(address):
        raise utils.CompileException('Can\'t load directly from register')

    if outerInner == None:
        comment = utils.formatComment('{} = {}'.format(outputReg, address),
                                      props, 2)
    else:
        comment = utils.formatComment(
            '{} = {}[{}]'.format(outputReg, outerInner[0], outerInner[1]),
            props, 2)

    return '{} {}, {}{}'.format(loadFunc, utils.getRegister(outputReg),
                                address, comment)
Beispiel #3
0
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 }
Beispiel #4
0
def loadAsAddress(address, outputReg, props, outerInner=None):
    if utils.isRegister(address):
        raise utils.CompileException('Can\'t load register as address')

    if outerInner == None:
        comment = utils.formatComment(
            '{} = address of {}'.format(outputReg, address), props, 2)
    else:
        comment = utils.formatComment(
            '{} = address of {}[{}]'.format(outputReg, outerInner[0],
                                            outerInner[1]), props, 2)

    return '{} {}, {}{}'.format('la', utils.getRegister(outputReg), address,
                                comment)
Beispiel #5
0
def storeToAddress(address, storeType, outputReg, props):
    if utils.isRegister(address):
        raise utils.CompileException('Can\'t store to register')
    numStoreFuncs = {
        'int': 'sw',
        'short': 'sh',
        'byte': 'sb',
        'char': 'sb',
        'number': 'sw'
    }
    storeFunc = 'sw'
    if storeType in definitions.NUM_TYPES: storeFunc = numStoreFuncs[storeType]

    comment = utils.formatComment('{} = {}'.format(address, outputReg), props,
                                  2)
    return '{} {}, {}{}'.format(storeFunc, utils.getRegister(outputReg),
                                address, comment)
Beispiel #6
0
def loadRegHiLo(reg, outputReg, props):
    comment = utils.formatComment('{} = {}'.format(outputReg, reg), props, 2)
    return 'mf{} {}{}'.format(reg[1:], utils.getRegister(outputReg), comment)
Beispiel #7
0
def isRegHiLo(reg):
    return utils.getRegister(reg) == '$hi' or utils.getRegister(reg) == '$lo'
Beispiel #8
0
def loadRegister(valueReg, outputReg, props):
    comment = utils.formatComment('{} = {}'.format(outputReg, valueReg), props,
                                  2)
    return 'add {}, $0, {}{}'.format(utils.getRegister(outputReg),
                                     utils.getRegister(valueReg), comment)
Beispiel #9
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
    }
Beispiel #10
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
    }
Beispiel #11
0
def parseGotoConditional(line, props):
    resultLines = []
    gotoFunc = line.split()[0]

    branchOperators = ['==', '!=', '<', '<=', '>', '>=']
    branchFuncs = {
        '==': 'beq',
        '!=': 'bne',
        '<': 'blt',
        '<=': 'ble',
        '>': 'bgt',
        '>=': 'bge'
    }
    branchFuncsWith0 = {'<': 'bltz', '<=': 'blez', '>': 'bgtz', '>=': 'bgez'}
    branchFuncsWith0Link = {'<': 'bltzal', '>=': 'bgezal'}

    condition = line.split(' if ')[1].strip()
    location = line.split(' if ')[0][len(gotoFunc):].strip()

    address = expressions.parseRHS(location, props, 'any',
                                   'address')['address']
    if address == None:
        raise utils.CompileException('Direct label is required')

    conditionLeft, conditionRight, conditionOperator = '', '', None

    splitCondition = parser.splitExpression(condition)
    rpnCondition = parser.infixToPostfix(splitCondition)
    if rpnCondition[-1] not in branchOperators:
        conditionLeft = '({})'.format(condition)
        conditionRight = '0'
        conditionOperator = '>'
    else:
        splitIdxCondition = [(item, idx)
                             for idx, item in enumerate(splitCondition)]
        rpnIdxCondition = parser.infixToPostfix(splitIdxCondition,
                                                lambda item: item[0])
        conditionOperator = rpnIdxCondition[-1][0]
        operatorIdx = rpnIdxCondition[-1][1]
        conditionLeft = ' '.join(splitCondition[:operatorIdx])
        conditionRight = ' '.join(splitCondition[operatorIdx + 1:])

    branchFunc = branchFuncs[conditionOperator]
    singleParam = False

    reg1, reg2 = 'any', 'any'
    if utils.isRegister(conditionLeft):
        reg1 = utils.getRegister(conditionLeft)
    else:
        parsed = expressions.parseRHS(conditionLeft, props, 'any', 'number')
        resultLines += parsed['lines']
        reg1 = parsed['reg']

    limitedProps = utils.propsWithTempRegExcl(props, [reg1])

    if gotoFunc == 'gotolink':
        if conditionRight == '0' and conditionOperator in branchFuncsWith0Link:
            branchFunc = branchFuncsWith0Link[conditionOperator]
            singleParam = True
        else:
            raise utils.CompileException(
                'Conditional gotolink only supports < 0 and >= 0 conditions')
    elif conditionRight == '0' and conditionOperator in branchFuncsWith0:
        branchFunc = branchFuncsWith0[conditionOperator]
        singleParam = True
    elif utils.isRegister(conditionRight):
        reg2 = utils.getRegister(conditionRight)
    else:
        parsed = expressions.parseRHS(conditionRight, limitedProps, 'any',
                                      'number')
        resultLines += parsed['lines']
        reg2 = parsed['reg']

    comment = utils.formatComment(line, props)
    if singleParam:
        resultLines.append('{} {}, {}{}'.format(branchFunc, reg1, address,
                                                comment))
    else:
        resultLines.append('{} {}, {}, {}{}'.format(branchFunc, reg1, reg2,
                                                    address, comment))
    return resultLines