diff --git a/README.md b/README.md index 525ee8039..a068d5450 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ which aims to provide many conveniences over raw assembly code (even when using - option to automatically run the compiled program in the Vice emulator - modularity, symbol scoping, subroutines - subroutines have enforced input- and output parameter definitions -- automatic variable allocations +- automatic variable allocations, automatic string variables and string sharing - various data types other than just bytes - automatic type conversions - floating point operations diff --git a/il65/codegen.py b/il65/codegen.py index da2fb2775..2dfd4e6e3 100644 --- a/il65/codegen.py +++ b/il65/codegen.py @@ -423,13 +423,15 @@ class CodeGenerator: raise CodeError("invalid incr/decr register") else: if stmt.what.register == 'A': - self.p("\t\tadc #{:d}".format(stmt.howmuch)) + self.p("\t\tsec") + self.p("\t\tsbc #{:d}".format(stmt.howmuch)) elif stmt.what.register in REGISTER_BYTES: if stmt.howmuch == 1: self.p("\t\tde{:s}".format(stmt.what.register.lower())) else: self.p("\t\tpha") self.p("\t\tt{:s}a".format(stmt.what.register.lower())) + self.p("\t\tsec") self.p("\t\tsbc #{:d}".format(stmt.howmuch)) self.p("\t\tta{:s}".format(stmt.what.register.lower())) self.p("\t\tpla") @@ -454,11 +456,11 @@ class CodeGenerator: self.p("\t\tclc") self.p("\t\tadc #{:d}".format(stmt.howmuch)) else: + self.p("\t\tsec") self.p("\t\tsbc #{:d}".format(stmt.howmuch)) self.p("\t\tsta " + r_str) self.p("\t\tpla") elif what.datatype == DataType.WORD: - # @todo verify this 16-bit incr/decr asm code if stmt.howmuch == 1: if is_incr: self.p("\t\tinc " + r_str) @@ -466,10 +468,12 @@ class CodeGenerator: self.p("\t\tinc {:s}+1".format(r_str)) self.p("+") else: - self.p("\t\tdec " + r_str) + self.p("\t\tpha") + self.p("\t\tlda " + r_str) self.p("\t\tbne +") self.p("\t\tdec {:s}+1".format(r_str)) - self.p("+") + self.p("+\t\tdec " + r_str) + self.p("\t\tpla") else: raise CodeError("cannot yet incr/decr 16 bit memory by more than 1") # @todo 16-bit incr/decr else: @@ -917,18 +921,20 @@ class CodeGenerator: def _generate_aug_reg_mem(self, lvalue: ParseResult.RegisterValue, operator: str, rvalue: ParseResult.MemMappedValue) -> None: r_str = rvalue.name or Parser.to_hex(rvalue.address) if operator == "+=": - self.p("\t\tclc") if lvalue.register == "A": + self.p("\t\tclc") self.p("\t\tadc " + r_str) elif lvalue.register == "X": self.p("\t\tpha") self.p("\t\ttxa") + self.p("\t\tclc") self.p("\t\tadc " + r_str) self.p("\t\ttax") self.p("\t\tpla") elif lvalue.register == "Y": self.p("\t\tpha") self.p("\t\ttya") + self.p("\t\tclc") self.p("\t\tadc " + r_str) self.p("\t\ttay") self.p("\t\tpla") @@ -936,16 +942,19 @@ class CodeGenerator: raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo +=.word elif operator == "-=": if lvalue.register == "A": + self.p("\t\tsec") self.p("\t\tsbc " + r_str) elif lvalue.register == "X": self.p("\t\tpha") self.p("\t\ttxa") + self.p("\t\tsec") self.p("\t\tsbc " + r_str) self.p("\t\ttax") self.p("\t\tpla") elif lvalue.register == "Y": self.p("\t\tpha") self.p("\t\ttya") + self.p("\t\tsec") self.p("\t\tsbc " + r_str) self.p("\t\ttay") self.p("\t\tpla") @@ -1010,18 +1019,20 @@ class CodeGenerator: def _generate_aug_reg_int(self, lvalue: ParseResult.RegisterValue, operator: str, rvalue: ParseResult.IntegerValue) -> None: r_str = rvalue.name or Parser.to_hex(rvalue.value) if operator == "+=": - self.p("\t\tclc") if lvalue.register == "A": + self.p("\t\tclc") self.p("\t\tadc #" + r_str) elif lvalue.register == "X": self.p("\t\tpha") self.p("\t\ttxa") + self.p("\t\tclc") self.p("\t\tadc #" + r_str) self.p("\t\ttax") self.p("\t\tpla") elif lvalue.register == "Y": self.p("\t\tpha") self.p("\t\ttya") + self.p("\t\tclc") self.p("\t\tadc #" + r_str) self.p("\t\ttay") self.p("\t\tpla") @@ -1029,16 +1040,19 @@ class CodeGenerator: raise CodeError("unsupported register for aug assign", str(lvalue)) # @todo +=.word elif operator == "-=": if lvalue.register == "A": + self.p("\t\tsec") self.p("\t\tsbc #" + r_str) elif lvalue.register == "X": self.p("\t\tpha") self.p("\t\ttxa") + self.p("\t\tsec") self.p("\t\tsbc #" + r_str) self.p("\t\ttax") self.p("\t\tpla") elif lvalue.register == "Y": self.p("\t\tpha") self.p("\t\ttya") + self.p("\t\tsec") self.p("\t\tsbc #" + r_str) self.p("\t\ttay") self.p("\t\tpla") @@ -1136,16 +1150,17 @@ class CodeGenerator: def _generate_aug_reg_reg(self, lvalue: ParseResult.RegisterValue, operator: str, rvalue: ParseResult.RegisterValue) -> None: if operator == "+=": - self.p("\t\tclc") if rvalue.register not in REGISTER_BYTES: raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo +=.word if lvalue.register == "A": self.p("\t\tst{:s} {:s}".format(rvalue.register.lower(), Parser.to_hex(Zeropage.SCRATCH_B1))) + self.p("\t\tclc") self.p("\t\tadc " + Parser.to_hex(Zeropage.SCRATCH_B1)) elif lvalue.register == "X": self.p("\t\tst{:s} {:s}".format(rvalue.register.lower(), Parser.to_hex(Zeropage.SCRATCH_B1))) self.p("\t\tpha") self.p("\t\ttxa") + self.p("\t\tclc") self.p("\t\tadc " + Parser.to_hex(Zeropage.SCRATCH_B1)) self.p("\t\ttax") self.p("\t\tpla") @@ -1153,6 +1168,7 @@ class CodeGenerator: self.p("\t\tst{:s} {:s}".format(rvalue.register.lower(), Parser.to_hex(Zeropage.SCRATCH_B1))) self.p("\t\tpha") self.p("\t\ttya") + self.p("\t\tclc") self.p("\t\tadc " + Parser.to_hex(Zeropage.SCRATCH_B1)) self.p("\t\ttay") self.p("\t\tpla") @@ -1163,11 +1179,13 @@ class CodeGenerator: raise CodeError("unsupported rvalue register for aug assign", str(rvalue)) # @todo -=.word if lvalue.register == "A": self.p("\t\tst{:s} {:s}".format(rvalue.register.lower(), Parser.to_hex(Zeropage.SCRATCH_B1))) + self.p("\t\tsec") self.p("\t\tsbc " + Parser.to_hex(Zeropage.SCRATCH_B1)) elif lvalue.register == "X": self.p("\t\tst{:s} {:s}".format(rvalue.register.lower(), Parser.to_hex(Zeropage.SCRATCH_B1))) self.p("\t\tpha") self.p("\t\ttxa") + self.p("\t\tsec") self.p("\t\tsbc " + Parser.to_hex(Zeropage.SCRATCH_B1)) self.p("\t\ttax") self.p("\t\tpla") @@ -1175,6 +1193,7 @@ class CodeGenerator: self.p("\t\tst{:s} {:s}".format(rvalue.register.lower(), Parser.to_hex(Zeropage.SCRATCH_B1))) self.p("\t\tpha") self.p("\t\ttya") + self.p("\t\tsec") self.p("\t\tsbc " + Parser.to_hex(Zeropage.SCRATCH_B1)) self.p("\t\ttay") self.p("\t\tpla") diff --git a/lib/c64lib.ill b/lib/c64lib.ill index c5c3e0ce6..1ab841c5b 100644 --- a/lib/c64lib.ill +++ b/lib/c64lib.ill @@ -333,6 +333,8 @@ sub GETADRAY () -> (AY, X?) { } } +; @todo optimize print_string()/ print_pstring() of a single character into a call to c64.CHROUT instead + sub print_string (address: XY) -> (A?, Y?) { ; ---- print null terminated string from X/Y asm { diff --git a/reference.md b/reference.md index ff4583ba9..6d96a0cc4 100644 --- a/reference.md +++ b/reference.md @@ -15,7 +15,7 @@ which aims to provide many conveniences over raw assembly code (even when using - option to automatically run the compiled program in the Vice emulator - modularity, symbol scoping, subroutines - subroutines have enforced input- and output parameter definitions -- automatic variable allocations +- automatic variable allocations, automatic string variables and string sharing - various data types other than just bytes - automatic type conversions - floating point operations diff --git a/testsource/numbergame.ill b/testsource/numbergame.ill index 4fddfca26..daee8756d 100644 --- a/testsource/numbergame.ill +++ b/testsource/numbergame.ill @@ -11,7 +11,6 @@ import "c64lib" var attempts_left = 10 start - c64util.init_system() A = c64.VMCSB A |= 2 ; @todo c64.VMCSB |= 2 c64.VMCSB = A @@ -41,8 +40,10 @@ printloop c64util.print_string("\nYou have ") c64util.print_byte_decimal(attempts_left) c64util.print_string(" guess") + + ; @todo comparison expression so we can do if attempts_left>0 ... A = attempts_left - A -= 1 ; @todo wrong instruction adc + A -- if_zero A goto ask_guess c64util.print_string("es") ask_guess @@ -52,7 +53,7 @@ ask_guess [$22.word] = guess c64.FREADSTR(A) AY = c64util.GETADRAY() - A -= secretnumber + A -= secretnumber ; @todo condition so we can do if guess > secretnumber.... if_zero goto correct_guess if_gt goto too_high c64util.print_string("That is too ")