Beispiel #1
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 #2
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 #3
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 #4
0
def parseAssignment(line, props):
    resultLines = []
    lhs, rhs = [s.strip() for s in line.split('=')]

    if utils.isRegister(lhs):
        reg = lhs.split(' as ')[0].strip() if ' as ' in lhs else lhs
        parsedRHS = expressions.parseRHS(rhs, props, reg)
        resultLines += parsedRHS['lines']
    else:
        inferredType = expressions.parseLHS(lhs, props)['type']
        parsedRHS = expressions.parseRHS(rhs, props, 'any', inferredType)
        resultLines += parsedRHS['lines']
        resultType = parsedRHS['type']
        limitedProps = utils.propsWithTempRegExcl(props, [parsedRHS['reg']])

        parsedLHS = expressions.parseLHS(lhs, limitedProps)
        resultLines += parsedLHS['lines']

        resultType = definitions.updateType(resultType, parsedLHS['elemtype'])
        resultLines.append(
            general.storeToAddress(parsedLHS['address'], resultType,
                                   parsedRHS['reg'], props))

    lastLine = resultLines[-1]
    if '#' in lastLine:
        lastLine = lastLine[:lastLine.index('#')].strip()
    resultLines[-1] = lastLine + utils.formatComment(line, props)
    return resultLines
Beispiel #5
0
def parseSysFunc(expr, props, isInExpression=False):
    comment = utils.formatComment(None if isInExpression else expr, props)
    if expr.startswith(utils.SYS_FUNCTIONS[0]):
        return [general.setMode(5, props), 'syscall{}'.format(comment)]
    elif expr.startswith(utils.SYS_FUNCTIONS[1]):
        params = expr[expr.index('(') + 1:-1].strip()
        parsedSize = expressions.parseRHS(params, props, '$a0')
        return parsedSize['lines'] + [
            general.setMode(9, props), 'syscall{}'.format(comment)
        ]
Beispiel #6
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 #7
0
def setMode(mode, props):
    modes = {
        1: 'print integer',
        4: 'print string',
        5: 'input integer',
        8: 'input string',
        9: 'allocate memory',
        10: 'exit',
        11: 'print character'
    }
    comment = utils.formatComment("set mode to '{}'".format(modes[mode]),
                                  props, 2)
    return 'addi $v0, $0, {}{}'.format(mode, comment)
Beispiel #8
0
def parseGoto(line, props, link=False):
    location = line[len('goto'):].strip()
    parsedExpr = expressions.parseRHS(location, props, 'any', 'address')
    locationReg = parsedExpr['reg']
    newComment = utils.formatComment(line, props)

    gotoInstructions = ['jal', 'jalr'] if link else ['j', 'jr']
    if parsedExpr['address'] != None:
        return '{} {}{}'.format(gotoInstructions[0], parsedExpr['address'],
                                newComment)
    else:
        return parsedExpr['lines'] + [
            '{} {}{}'.format(gotoInstructions[1], locationReg, newComment)
        ]
Beispiel #9
0
def parsePrint(line, props):
    parsedExpr = expressions.parseRHS(line[line.index(' '):].strip(), props,
                                      '$a0')
    printOperations = {'number': 1, 'address': 4, 'char': 11}
    resultType = 'char' if parsedExpr[
        'type'] == 'char' else definitions.getSupertype(parsedExpr['type'])
    if resultType == 'any': resultType = 'number'
    printOperation = printOperations[resultType if resultType in
                                     printOperations else 'number']

    return parsedExpr['lines'] + [
        general.setMode(printOperation, props), 'syscall{}'.format(
            utils.formatComment(line, props))
    ]
Beispiel #10
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 #11
0
def parseInputStr(line, props):
    resultLines = []
    argumentStr = line[len(line.split()[0]):]
    arguments = [s.strip() for s in argumentStr.split(',')]
    parsedAddr = expressions.parseRHS(arguments[0], props, '$a0', 'address')
    resultLines += parsedAddr['lines']

    maxSize = '20'
    if len(arguments) > 1: maxSize = arguments[1]
    elif arguments[0] in props['variables']:
        maxSize = str(props['variables'][arguments[0]]['initsize'])

    parsedSize = expressions.parseRHS(maxSize, props, '$a1', 'number')
    resultLines += parsedSize['lines']

    return resultLines + [
        general.setMode(8, props), 'syscall{}'.format(
            utils.formatComment(line, props))
    ]
Beispiel #12
0
def loadRegHiLo(reg, outputReg, props):
    comment = utils.formatComment('{} = {}'.format(outputReg, reg), props, 2)
    return 'mf{} {}{}'.format(reg[1:], utils.getRegister(outputReg), comment)
Beispiel #13
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 #14
0
def parseDefinition(line, props):
    newLine = ''
    newVariable = {}

    varDefinition, varValue = '', None
    if '=' in line:
        varDefinition, varValue = [s.strip() for s in line.split('=')]
    else:
        varDefinition = line.strip()
    varType, varName = varDefinition.split()

    comment = utils.formatComment(varDefinition, props)

    # Numberic
    numTypeMap = {
        'int': 'word',
        'short': 'half',
        'byte': 'byte',
        'char': 'byte'
    }
    for numType in NUM_TYPES:
        if varValue == None: varValue = '0'
        if varType == numType:
            parsedValue = utils.getIntOrChar(varValue)
            newLine = '{}: .{} {}{}'.format(varName, numTypeMap[numType],
                                            parsedValue, comment)
            newVariable = {
                'name': varName,
                'type': varType,
                'supertype': getSupertype(varType),
                'init': varValue
            }

    # Array or string or address
    if varType in ADDRESS_TYPES or '[' in varType:
        initSize = 0
        if '[' in varType:
            initSizeStr = varType[varType.index('[') + 1:varType.index(']')]
            initSize = utils.getIntOrChar(initSizeStr) if utils.isInt(
                initSizeStr) else 0
            varType = varType[:varType.index('[')].strip() + '[]'
        elemType = ADDRESS_ELEMENT_TYPE_MAP[varType]

        if varValue[0] == '\'' and varValue[-1] == '\'':
            varValue = '"' + varValue[1:-1] + '"'
        if varValue.startswith('"'):
            newLine = '{}: .asciiz {}{}'.format(varName, varValue, comment)
        elif varValue.startswith('['):
            newLine = '{}: .{} {}{}'.format(varName, numTypeMap[elemType],
                                            varValue[1:-1].strip(), comment)
        else:
            numBytes = NUM_SIZES[elemType]
            newLine = '{}: .space {}{}'.format(varName, initSize, comment)
            if numBytes != 1:
                newLine = '.align {}{}{}'.format(numBytes - 1, os.linesep,
                                                 newLine)

        newVariable = {
            'name': varName,
            'type': varType,
            'supertype': 'address',
            'elemtype': ADDRESS_ELEMENT_TYPE_MAP[varType],
            'init': varValue,
            'initsize': initSize
        }

    if props['comment'] is not None: newLine += props['comment']
    return (newLine, newVariable)
Beispiel #15
0
def parseExit(line, props):
    return [
        general.setMode(10, props),
        'syscall{}'.format(utils.formatComment('exit', props))
    ]
Beispiel #16
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