Exemplo n.º 1
0
def _genShiftLargeCall(resultLoc, src1Loc, src2Loc, label):
    result = f'; {resultLoc} = shift {src1Loc}, {src2Loc}\n'
    s2 = src2Loc.getSource()
    s1 = src1Loc.getSource()
    rs = resultLoc.getSource()
    if src2Loc.getType().getSize() == 2:
        raise NatrixNotImplementedError(Position.fromAny(src2Loc),
                                        "Shift large by word")
    result += loadByte('a', src2Loc, 0)
    result += f'''
        ldi pl, lo(__cc_sh_count)
        ldi ph, hi(__cc_sh_count)
        st a
    '''
    size = src1Loc.getType().getSize()
    for offset in range(0, size, 2):
        rest = size - offset
        pCode, p = _adjustP(src1Loc, offset, None)
        result += pCode
        result += 'ld a\n'
        if rest > 1:
            pCode, p = _adjustP(src1Loc, offset + 1, p)
            result += pCode
            result += 'ld b\n'
        result += f'''
            ldi pl, lo(__cc_sh_val + {offset})
            ldi ph, hi(__cc_sh_val + {offset})
            st a
        '''
        if rest > 1:
            result += '''
                inc pl
                st b
            '''
    result += f'''
        ldi pl, lo({label})
        ldi ph, hi({label})
        jmp
    '''
    for offset in range(0, size, 2):
        result += f'''
            ldi pl, lo(__cc_sh_val + {offset})
            ldi ph, hi(__cc_sh_val + {offset})
            ld a
        '''
        if rest > 1:
            result += '''
                inc pl
                ld b
            '''
        p = None
        rest = size - offset
        pCode, p = _adjustP(resultLoc, offset, p)
        result += pCode
        result += 'st a\n'
        if rest > 1:
            pCode, p = _adjustP(resultLoc, offset + 1, p)
            result += pCode
            result += 'st b\n'
    return resultLoc, result
Exemplo n.º 2
0
def genNeg(resultLoc, srcLoc):
    if resultLoc.getType().isUnknown():
        resultLoc = resultLoc.removeUnknown(srcLoc.getType())
    if resultLoc.getType() != srcLoc.getType():
        raise SemanticError(
            srcLoc.getPosition(),
            "Incompatible types: {} and {}".format(resultLoc.getType(),
                                                   srcLoc.getType()))
    if not srcLoc.getType().getSign():
        raise SemanticError(
            srcLoc.getPosition(),
            "Argument for unary `-' should be of a signed type")
    assert (resultLoc.getIndirLevel() == 1)
    assert (srcLoc.getIndirLevel() == 1 or srcLoc.getIndirLevel() == 0)

    t = srcLoc.getType()
    if t.getSize() > 2:
        raise NatrixNotImplementedError(
            srcLoc.getPosition(),
            "Negation of ints wider than s16 is not implemented")
    result = '; {} = -{}\n'.format(resultLoc, srcLoc)
    if srcLoc.getIndirLevel() == 0:
        # constant
        c = srcLoc.getSource()
        if c.isNumber():
            c = -int(c) & (0xff if t.getSize() == 1 else 0xffff)
        else:
            c = '-({})'.format(c)  # Warning
        return Value(srcLoc.getPosition(), t, 0, c, True), result
    else:
        # var
        if t.getSize() == 1:
            result += loadByte('a', srcLoc, 0)
            result += 'neg a\n'
            return Value.register(srcLoc.getPosition(), t), result
        else:
            result += f'''
                ldi pl, lo({srcLoc.getSource()})
                ldi ph, hi({srcLoc.getSource()})
                ld b
            '''
            result += incP(srcLoc.isAligned())
            result += '''
                ld a
                not a
                not b
                inc b
                adc a, 0
            '''
        result += f'''
            ldi pl, lo({resultLoc.getSource()})
            ldi ph, hi({resultLoc.getSource()})
            st b
        '''
        result += incP(resultLoc.isAligned())
        result += '''
            st a
        '''
        return resultLoc, result
Exemplo n.º 3
0
def _genSARByVar(resultLoc, src1Loc, src2Loc, labelProvider):
    size = src1Loc.getType().getSize()
    if size == 1:
        return _genShByteByVar(resultLoc, src1Loc, src2Loc, labelProvider,
                               "sar")
    elif size == 2:
        return _genShiftWordCall(resultLoc, src1Loc, src2Loc, "__cc_asr")
    else:
        raise NatrixNotImplementedError(Position.fromAny(resultLoc),
                                        "SAR large by var")
Exemplo n.º 4
0
def _genShByteByVar(resultLoc, src1Loc, src2Loc, labelProvider, op):
    if src2Loc.getType().getSize() > 1:
        raise NatrixNotImplementedError(src2Loc.getPosition(),
                                        "Shift by variables over 8 bits")
    lBegin = labelProvider.allocLabel("shift_begin")
    lLoop = labelProvider.allocLabel("shift_loop")
    lEnd = labelProvider.allocLabel("shift_end")
    lInf = labelProvider.allocLabel("shift_inf")
    if src1Loc.getSource().isRegister():
        raise RegisterNotSupportedError(0)
    result = '; {} = {} {}, {} (byte)\n'.format(resultLoc, op, src1Loc,
                                                src2Loc)
    result += loadByte('a', src2Loc, 0)
    result += f'''
        ldi b, 7
        sub b, a
        ldi pl, lo({lBegin})
        ldi ph, hi({lBegin})
        jnc ; a <= 7
    {lInf}:
    '''
    if src1Loc.getType().getSign() and op != 'shl':
        result += loadByte('b', src1Loc, 0)
        result += '''
            shl b
            exp b
        '''
    else:
        result += 'ldi b, 0\n'
    result += f'''
        ldi pl, lo({lEnd})
        ldi ph, hi({lEnd})
        jmp
    {lBegin}:
    '''
    result += loadByte('b', src1Loc, 0)
    result += f'''
        ldi pl, lo({lEnd})
        ldi ph, hi({lEnd})
        add a, 0
        jz ; a == 0
    {lLoop}:
        {op} b
        dec a
        ldi pl, lo({lLoop})
        ldi ph, hi({lLoop})
        jnz
    {lEnd}:
        mov a, b
    '''
    return Value.register(resultLoc.getPosition(), resultLoc.getType()), result
Exemplo n.º 5
0
def genShift(resultLoc, src1Loc, src2Loc, op, labelProvider):
    assert (resultLoc.getIndirLevel() == 1)
    t = src1Loc.getType()
    if not t.isInteger():
        raise SemanticError(src1Loc.getPosition(), "Can only shift integers")
    if not src2Loc.getType().isInteger() or src2Loc.getType().getSign():
        raise SemanticError(src2Loc.getPosition(),
                            "Can only shift by unsigned integers")
    resultLoc = resultLoc.withType(t)
    l1 = src1Loc.getIndirLevel()
    l2 = src2Loc.getIndirLevel()
    assert (l1 == 0 or l1 == 1)
    assert (l2 == 0 or l2 == 1)
    if l1 == 0 and l2 == 0:
        raise NatrixNotImplementedError(Position.fromAny(resultLoc),
                                        "Stop doing shit with pointers!")
    if l2 == 0:
        c = src2Loc.getSource()
        if c.isNumber():
            if op == 'shl':
                return genSHLVarByConst(resultLoc, src1Loc, int(c))
            elif op == 'shr':
                if t.getSign():
                    return _genSARVarByConst(resultLoc, src1Loc, int(c))
                else:
                    return _genSHRVarByConst(resultLoc, src1Loc, int(c))
        else:
            raise NatrixNotImplementedError(Position.fromAny(resultLoc),
                                            "Stop doing shit with pointers!")
    else:
        if op == 'shl':
            return _genSHLByVar(resultLoc, src1Loc, src2Loc, labelProvider)
        elif op == 'shr':
            if t.getSign():
                return _genSARByVar(resultLoc, src1Loc, src2Loc, labelProvider)
            else:
                return _genSHRByVar(resultLoc, src1Loc, src2Loc, labelProvider)
Exemplo n.º 6
0
def _genCmpSigned(resultLoc, src1Loc, src2Loc, op, labelProvider):
    s1 = src1Loc.getSource()
    s2 = src2Loc.getSource()
    rs = resultLoc.getSource()
    l1 = src1Loc.getIndirLevel()
    l2 = src2Loc.getIndirLevel()
    t = src1Loc.getType()
    if l1 == 0 and l2 == 0:
        # const and const
        raise NatrixNotImplementedError(src1Loc.getPosition(),
                                        "signed const comparison")
    else:
        if t.getSize() == 1:
            return _genCmpSignedByte(resultLoc, src1Loc, src2Loc, op,
                                     labelProvider)
        elif t.getSize() == 2:
            return _genCmpSignedWord(resultLoc, src1Loc, src2Loc, op,
                                     labelProvider)
        else:
            return _genCmpSignedLong(resultLoc, src1Loc, src2Loc, op,
                                     labelProvider)
Exemplo n.º 7
0
def _genSubPtr(resultLoc, src1Loc, src2Loc):
    if not src2Loc.getType().isInteger():
        raise SemanticError(src2Loc.getPosition(),
            "Can only subtract ponters and integers, not pointers and other types")
    memberSize = src1Loc.getType().deref().getSize()
    s1 = src1Loc.getSource()
    s2 = src2Loc.getSource()
    rs = resultLoc.getSource()
    t = resultLoc.getType()
    result = '; {} = {} - {} * {}\n'.format(resultLoc, src1Loc, src2Loc, memberSize)
    isWord = src2Loc.getType().getSize() == 2
    if memberSize > 2:
        if src2Loc.getIndirLevel() == 0:
            pos = src1Loc.getPosition() - src2Loc.getPosition()
            offset = s2 * memberSize
            loc, code = _genIntBinary(resultLoc, src1Loc, Value(pos, t, 0, offset, True), "sub", "sbb", "({}) - ({})", operator.sub, False)
            return loc, result + code
        elif not isPowerOfTwo(memberSize):
            raise NatrixNotImplementedError(src2Loc.getPosition(), f"sizeof({src1Loc.getType().deref()}) = {memberSize} is not a power of two")
        elif src1Loc == resultLoc:
            shift = log(memberSize)
            loc, code = _genIncDecPtr(resultLoc, src2Loc, shift, "sub", "sbb")
            return loc, result + code
        else:
            shift = log(memberSize)
            shiftedLoc, shiftCode = genSHLVarByConst(resultLoc, src2Loc, shift)
            loc, subtractionCode = _genIntBinary(resultLoc, src1Loc, shiftedLoc, "sub", "sbb", "({}) - ({})", operator.sub, False)
            return loc, result + shiftCode + subtractionCode
    elif isWord:
        assert(not src2Loc.getSource().isRegister())
        if memberSize == 1:
            # no multiplication, just subtract
            loc, code = _genIntBinary(resultLoc, src1Loc, src2Loc.withType(t), "sub", "sbb", "({}) - ({})", operator.sub, False)
            return loc, result + code
        elif memberSize == 2:
            if src2Loc.getIndirLevel() == 0:
                pos = src1Loc.getPosition() - src2Loc.getPosition()
                offset = s2 * 2
                loc, code = _genIntBinary(resultLoc, src1Loc, Value(pos, t, 0, offset, True), "sub", "sbb", "({}) - ({})", operator.sub, False)
                return loc, result + code
            else:
                result += '''
                    ldi pl, lo({0})
                    ldi ph, hi({0})
                    ld b
                '''.format(s2)
                if src2Loc.isAligned():
                    result += 'inc pl\n'
                else:
                    result += '''
                        ldi pl, lo({0} + 1)
                        ldi ph, hi({0} + 1)
                    '''.format(s2)
                result += '''
                    ld a
                    shl a
                    shl b
                    adc a, 0
                '''
                if src1Loc.getIndirLevel() == 1:
                    result += '''
                        xor a, b
                        xor b, a
                        xor a, b
                        ldi pl, lo({0})
                        ldi ph, hi({0})
                        ld pl
                        sub pl, a
                        mov a, pl
                        ldi ph, hi({0} + 1)
                        ldi pl, lo({0} + 1)
                        ld pl
                        mov ph, a
                        mov a, pl
                        sbb a, b
                        mov b, a
                        mov a, ph
                    '''.format(s1)
                else:
                    # a:b - index
                    result += '''
                        mov ph, a
                        ldi a, lo({0})
                        sub b, a
                        ldi a, hi({0})
                        sbb ph, a
                        mov a, ph
                    '''.format(s1)
                result += '''
                    ldi pl, lo({0})
                    ldi ph, hi({0})
                    st a
                    inc pl
                '''.format(rs)
                if not resultLoc.isAligned():
                    result += '''
                        mov a, 0
                        adc ph, a
                    '''
                result += 'st b\n'
    else: # not isWord
        if src2Loc.getIndirLevel() == 0:
            pos = src1Loc.getPosition() - src2Loc.getPosition()
            s2 = s2.widen(src2Loc.getType().getSign())
            offset = s2 * memberSize
            loc, code = _genIntBinary(resultLoc, src1Loc, Value(pos, t, 0, offset, True), "sub", "sbb", "({}) - ({})", operator.sub, False)
            return loc, result + code
        if src2Loc.getType().getSign():
            raise SemanticError(src2Loc.getPosition(), "pointer arithmetic with s8 is not implemented")
        # s2.indirLevel == 1
        result += loadByte('b', src2Loc, 0)
        if memberSize == 1:
            if src1Loc.getIndirLevel() == 0:
                result += '''
                    ldi a, lo({0})
                    sub a, b
                    mov b, a
                    ldi a, hi({0})
                    sbb a, 0
                '''.format(src1Loc.getSource())
            else:
                result += '''
                    ldi pl, lo({0})
                    ldi ph, hi({0})
                    ld a
                    sub a, b
                    mov b, a
                    ldi pl, lo({0} + 1)
                    ldi ph, hi({0} + 1)
                    ld a
                    sbb a, 0
                '''.format(src1Loc.getSource())
        elif memberSize == 2:
            if src1Loc.getIndirLevel() == 0:
                result += '''
                    mov a, 0
                    mov pl, a
                    shl b
                    adc pl, a
                    ldi a, lo({0})
                    sub a, b
                    mov b, a
                    ldi a, hi({0})
                    sbb a, pl
                '''.format(src1Loc.getSource())
            else:
                result += '''
                    ldi pl, lo({0})
                    ldi ph, hi({0})
                    ld pl ; pl = p_l
                    mov a, 0
                    shl b ; b = i_l
                    adc a, 0
                    mov ph, a ; ph = i_h
                    mov a, pl ; a = p_l
                    sub a, b ; a = r_l
                    mov b, a ; b = r_l
                    mov a, 0
                    adc a, 0 ; a = c
                    add a, ph ; a = i_h + c
                    ldi pl, lo({0} + 1)
                    ldi ph, hi({0} + 1)
                    ld pl ; pl = p_h
                    sub pl, a
                    mov a, pl ; a = p_h - (i_h + c) = r_h
                '''.format(src1Loc.getSource())
        else:
            raise RuntimeError("Other sizes than 1 and 2 are not supported for pointer indexing")
        result += '''
            ldi pl, lo({0})
            ldi ph, hi({0})
            st b
        '''.format(resultLoc.getSource())
        if resultLoc.isAligned():
            result += 'inc pl\n'
        else:
            result += '''
                ldi pl, lo({0} + 1)
                ldi ph, hi({0} + 1)
            '''.format(resultLoc.getSource())
        result += 'st a\n'
    return resultLoc, result
Exemplo n.º 8
0
def _genAddPtr(resultLoc, src1Loc, src2Loc):
    if not src2Loc.getType().isInteger():
        raise SemanticError(src2Loc.getPosition(),
            "Can only add ponters and integers, not pointers and other types")
    memberSize = src1Loc.getType().deref().getSize()
    s1 = src1Loc.getSource()
    s2 = src2Loc.getSource()
    rs = resultLoc.getSource()
    t = resultLoc.getType()
    if src2Loc.getType().getSize() > 2:
        raise NatrixNotImplementedError(src2Loc.getPosition(), "Can only add integers up to 16 bit to pointers")
    result = '; {} = {} + {} * {}\n'.format(resultLoc, src1Loc, src2Loc, memberSize)
    isWord = src2Loc.getType().getSize() == 2
    if memberSize > 2:
        if src2Loc.getIndirLevel() == 0:
            pos = src1Loc.getPosition() - src2Loc.getPosition()
            offset = s2 * memberSize
            loc, code = _genIntBinary(resultLoc, src1Loc, Value(pos, t, 0, offset, True), "add", "adc", "({}) + ({})", operator.add, False)
            return loc, result + code
        elif not isPowerOfTwo(memberSize):
            raise NatrixNotImplementedError(src2Loc.getPosition(), f"sizeof({src1Loc.getType().deref()}) = {memberSize} is not a power of two")
        elif src1Loc == resultLoc:
            shift = log(memberSize)
            loc, code = _genIncDecPtr(resultLoc, src2Loc, shift, "add", "adc")
            return loc, result + code
        else:
            shift = log(memberSize)
            shiftedLoc, shiftCode = genSHLVarByConst(resultLoc, src2Loc, shift)
            loc, additionCode = _genIntBinary(resultLoc, shiftedLoc, src1Loc, "add", "adc", "({}) + ({})", operator.add, False)
            return loc, result + shiftCode + additionCode
    elif isWord:
        assert(not src2Loc.getSource().isRegister())
        if memberSize == 1:
            # no multiplication, just add
            loc, code = _genIntBinary(resultLoc, src1Loc, src2Loc.withType(t), "add", "adc", "({}) + ({})", operator.add, False)
            return loc, result + code
        elif memberSize == 2:
            if src2Loc.getIndirLevel() == 0:
                pos = src1Loc.getPosition() - src2Loc.getPosition()
                offset = s2 * 2
                loc, code = _genIntBinary(resultLoc, src1Loc, Value(pos, t, 0, offset, True), "add", "adc", "({}) + ({})", operator.add, False)
                return loc, result + code
            else:
                result += '''
                    ldi pl, lo({0})
                    ldi ph, hi({0})
                    ld b
                    inc pl
                '''.format(s2)
                if not src2Loc.isAligned():
                    result += '''
                        mov a, 0
                        adc ph, a
                    '''
                result += '''
                    ld a
                    shl a
                    shl b
                    adc a, 0
                '''
                if src1Loc.getIndirLevel() == 1:
                    result += '''
                        xor a, b
                        xor b, a
                        xor a, b
                        ldi pl, lo({0})
                        ldi ph, hi({0})
                        ld pl
                        add a, pl
                        ldi ph, hi({0} + 1)
                        ldi pl, lo({0} + 1)
                        ld pl
                        mov ph, a
                        mov a, pl
                        adc b, a
                        mov a, ph
                    '''.format(s1)
                    result += '''
                        ldi pl, lo({0})
                        ldi ph, hi({0})
                        st a
                        inc pl
                    '''.format(rs)
                    if not resultLoc.isAligned():
                        result += '''
                            mov a, 0
                            adc ph, a
                        '''
                    result += '''
                        st b
                    '''
                else:
                    # a:b - index
                    result += '''
                        mov ph, a
                        ldi a, lo({0})
                        add b, a
                        ldi a, hi({0})
                        adc a, ph
                    '''.format(s1)
                    result += '''
                        ldi pl, lo({0})
                        ldi ph, hi({0})
                        st b
                    '''.format(rs)
                    if resultLoc.isAligned():
                        result += '''
                            inc pl
                            st a
                        '''
                    else:
                        result += '''
                            ldi pl, lo({0} + 1)
                            ldi ph, hi({0} + 1)
                            st a
                        '''.format(rs)
    else: # not isWord
        if src2Loc.getIndirLevel() == 0:
            pos = src1Loc.getPosition() - src2Loc.getPosition()
            s2 = s2.widen(src2Loc.getType().getSign())
            offset = s2 * memberSize
            loc, code = _genIntBinary(resultLoc, src1Loc, Value(pos, t, 0, offset, True), "add", "adc", "({}) + ({})", operator.add, False)
            return loc, result + code
        if src2Loc.getType().getSign():
            raise SemanticError(src2Loc.getPosition(), "pointer arithmetic with s8 is not implemented")
        # s2.indirLevel == 1
        result += loadByte('b', src2Loc, 0)
        if memberSize == 1:
            if src1Loc.getIndirLevel() == 0:
                result += '''
                    ldi a, lo({0})
                    add b, a
                    ldi a, hi({0})
                    adc a, 0
                '''.format(src1Loc.getSource())
            else:
                result += '''
                    ldi pl, lo({0})
                    ldi ph, hi({0})
                    ld a
                    add b, a
                    ldi pl, lo({0} + 1)
                    ldi ph, hi({0} + 1)
                    ld a
                    adc a, 0
                '''.format(src1Loc.getSource())
        elif memberSize == 2:
            if src1Loc.getIndirLevel() == 0:
                result += '''
                    mov a, 0
                    mov pl, a
                    shl b
                    adc pl, a
                    ldi a, lo({0})
                    add b, a
                    ldi a, hi({0})
                    adc a, pl
                '''.format(src1Loc.getSource())
            else:
                result += '''
                    ldi pl, lo({0})
                    ldi ph, hi({0})
                    ld pl ; pl = p_l
                    mov a, 0
                    shl b ; b = i_l
                    adc a, 0
                    mov ph, a ; ph = i_h
                    mov a, pl
                    add b, a ; b = p_l + i_l = r_l
                    mov a, 0
                    adc a, 0 ; a = c
                    add a, ph ; a = i_h + c
                    ldi pl, lo({0} + 1)
                    ldi ph, hi({0} + 1)
                    ld pl
                    add a, pl ; a = i_h + c + p_h = r_h
                '''.format(src1Loc.getSource())
        if resultLoc.isAligned():
            result += '''
                ldi pl, lo({0})
                ldi ph, hi({0})
                st b
                inc pl
                st a
            '''.format(resultLoc.getSource())
        else:
            result += '''
                ldi pl, lo({0})
                ldi ph, hi({0})
                st b
                ldi pl, lo({0} + 1)
                ldi ph, hi({0} + 1)
                st a
            '''.format(resultLoc.getSource())
    return resultLoc, result