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
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
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")
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
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)
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)
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
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