float incr/decr by 1

This commit is contained in:
Irmen de Jong 2017-12-31 15:50:50 +01:00
parent 3b0d6e969b
commit 3dcfa42574
5 changed files with 80 additions and 10 deletions

View File

@ -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:

View File

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

View File

@ -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)]

View File

@ -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
ldy #>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
ldy #>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
}
}

View File

@ -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