diff --git a/il65/astdefs.py b/il65/astdefs.py index f99dbf9b3..d10b2cd28 100644 --- a/il65/astdefs.py +++ b/il65/astdefs.py @@ -307,7 +307,9 @@ class MemMappedValue(Value): if self.constant: return False, "cannot assign to a constant" if isinstance(other, IndirectValue): - return False, "can not yet assign memory mapped value from indirect value" # @todo indirect v assign + if self.datatype == other.datatype: + return True, "" + return False, "data type of value and target are not the same" if self.datatype == DataType.BYTE: if isinstance(other, (IntegerValue, RegisterValue, MemMappedValue)): if other.datatype == DataType.BYTE: diff --git a/il65/codegen.py b/il65/codegen.py index f74a8bf7c..b1a5010c8 100644 --- a/il65/codegen.py +++ b/il65/codegen.py @@ -395,13 +395,9 @@ class CodeGenerator: self.previous_stmt_was_assignment = isinstance(stmt, AssignmentStmt) def generate_incr_or_decr(self, stmt: Union[InplaceIncrStmt, InplaceDecrStmt]) -> None: - if stmt.what.datatype == DataType.FLOAT: - raise CodeError("incr/decr on float not yet supported") # @todo support incr/decr on float - else: - assert type(stmt.howmuch) is int assert stmt.howmuch > 0 - if stmt.howmuch > 0xff: - raise CodeError("only supports incr/decr by up to 255 for now") # XXX + if stmt.what.datatype != DataType.FLOAT and stmt.howmuch > 0xff: + raise CodeError("only supports integer incr/decr by up to 255 for now") # XXX is_incr = isinstance(stmt, InplaceIncrStmt) if isinstance(stmt.what, RegisterValue): reg = stmt.what.register @@ -564,8 +560,20 @@ class CodeGenerator: self.p("\t\tbcs +") self.p("\t\tdec {:s}+1".format(r_str)) self.p("+\t\tpla") + elif what.datatype == DataType.FLOAT: + if stmt.howmuch == 1.0: + t_str = stmt.what.name or Parser.to_hex(stmt.what.address) + with self.preserving_registers({'A', 'X', 'Y'}, loads_a_within=True): + self.p("\t\t ldx #<" + t_str) + self.p("\t\t ldy #>" + t_str) + if is_incr: + self.p("\t\t jsr il65_lib.float_add_one") + else: + self.p("\t\t jsr il65_lib.float_sub_one") + else: + raise CodeError("cannot incr/decr float by other than 1 at this time", stmt.howmuch) # XXX else: - raise CodeError("cannot in/decrement memory of type " + str(what.datatype)) + raise CodeError("cannot in/decrement memory of type " + str(what.datatype), stmt.howmuch) else: raise CodeError("cannot in/decrement " + str(stmt.what)) diff --git a/il65/parse.py b/il65/parse.py index 94bbabfd9..53aa2c4e2 100644 --- a/il65/parse.py +++ b/il65/parse.py @@ -1163,7 +1163,7 @@ class Parser: if datatype in (DataType.BYTE, DataType.WORD, DataType.MATRIX) and type(value) is float: frac = math.modf(value) # type:ignore if frac != 0: - self.print_warning("float value truncated") + self.print_warning("float value truncated ({} to datatype {})".format(value, datatype.name)) return True, int(value) return False, value @@ -1333,7 +1333,8 @@ class Optimizer: def remove_unused_subroutines(self, block: Block) -> None: # some symbols are used by the emitted assembly code from the code generator, # and should never be removed or the assembler will fail - never_remove = {"c64.GIVUAYF", "c64.FREADUY", "c64.FTOMEMXY"} + # @todo make this dynamic + never_remove = {"c64.GIVUAYF", "c64.FREADUY", "c64.FTOMEMXY", "c64.FADD", "c64.FSUB"} discarded = [] for sub in list(block.symbols.iter_subroutines()): usages = self.parsed.subroutine_usage[(sub.blockname, sub.name)] diff --git a/lib/il65lib.ill b/lib/il65lib.ill index 857844744..cc4b594f3 100644 --- a/lib/il65lib.ill +++ b/lib/il65lib.ill @@ -121,4 +121,35 @@ copy_mflt stx SCRATCH_ZP1 ldy SCRATCH_ZPWORD1+1 rts } + + asm { + +; ---- add 1 to the MFLT pointed to by X/Y. Clobbers A, X, Y +float_add_one + stx SCRATCH_ZP1 + sty SCRATCH_ZP2 + txa + jsr c64.MOVFM ; fac1 = float XY + lda #c64.FL_FONE + jsr c64.FADD ; fac1 += 1 + ldx SCRATCH_ZP1 + ldy SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + +; ---- subtract 1 from the MFLT pointed to by X/Y. Clobbers A, X, Y +float_sub_one + stx SCRATCH_ZP1 + sty SCRATCH_ZP2 + lda #c64.FL_FONE + jsr c64.MOVFM ; fac1 = 1 + txa + ldy SCRATCH_ZP2 + jsr c64.FSUB ; fac1 = float XY - 1 + ldx SCRATCH_ZP1 + ldy SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + + } } diff --git a/todo.ill b/todo.ill index 6cc40885e..994143b2e 100644 --- a/todo.ill +++ b/todo.ill @@ -5,7 +5,35 @@ output prg,basic import "c64lib" ~ main { + + var .float float1 = 123.456 start + c64.MOVFM(#float1) + c64.FPRINTLN() + float1++ + c64.MOVFM(#float1) + c64.FPRINTLN() + float1-=1 + c64.MOVFM(#float1) + c64.FPRINTLN() + float1-- + c64.MOVFM(#float1) + c64.FPRINTLN() + ;float1+=0.5 + ;c64.MOVFM(#float1) + ;c64.FPRINTLN() + ;float1+=2235.55 + ;c64.MOVFM(#float1) + ;c64.FPRINTLN() + ;float1-=999.55 + ;c64.MOVFM(#float1) + ;c64.FPRINTLN() + ;float1-=33333.456 + ;c64.MOVFM(#float1) + ;c64.FPRINTLN() + + return + A = $11 X = $22 Y = $33