mirror of
https://github.com/irmen/prog8.git
synced 2024-09-11 00:54:31 +00:00
incrdecr codegen
This commit is contained in:
parent
76755cf57d
commit
a560982b7e
@ -83,7 +83,6 @@ class PlyParser:
|
|||||||
if node.datatype == DataType.FLOAT:
|
if node.datatype == DataType.FLOAT:
|
||||||
raise ParseError("floating point numbers not enabled via option", node.sourceref)
|
raise ParseError("floating point numbers not enabled via option", node.sourceref)
|
||||||
|
|
||||||
|
|
||||||
def coerce_values(self, module: Module) -> None:
|
def coerce_values(self, module: Module) -> None:
|
||||||
for node in module.all_nodes():
|
for node in module.all_nodes():
|
||||||
try:
|
try:
|
||||||
@ -182,6 +181,9 @@ class PlyParser:
|
|||||||
elif isinstance(node, VarDef):
|
elif isinstance(node, VarDef):
|
||||||
if node.value is not None and not node.value.is_compile_constant():
|
if node.value is not None and not node.value.is_compile_constant():
|
||||||
raise ParseError("variable initialization value should be a compile-time constant", node.value.sourceref)
|
raise ParseError("variable initialization value should be a compile-time constant", node.value.sourceref)
|
||||||
|
elif isinstance(node, Dereference):
|
||||||
|
if isinstance(node.operand, Register) and node.operand.datatype == DataType.BYTE:
|
||||||
|
raise ParseError("can't dereference a single register; use a register pair", node.operand.sourceref)
|
||||||
previous_stmt = node
|
previous_stmt = node
|
||||||
|
|
||||||
def check_subroutine_arguments(self, call: SubCall, subdef: Subroutine) -> None:
|
def check_subroutine_arguments(self, call: SubCall, subdef: Subroutine) -> None:
|
||||||
|
@ -8,9 +8,9 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from ..plyparse import Scope, VarType, VarDef, Register, IncrDecr, SymbolName, Dereference, datatype_of
|
from ..plyparse import Scope, VarType, VarDef, Register, IncrDecr, SymbolName, Dereference, LiteralValue, datatype_of
|
||||||
from ..datatypes import DataType, REGISTER_BYTES
|
from ..datatypes import DataType, REGISTER_BYTES
|
||||||
from . import CodeError, preserving_registers
|
from . import CodeError, preserving_registers, to_hex
|
||||||
|
|
||||||
|
|
||||||
def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enabled: bool) -> None:
|
def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enabled: bool) -> None:
|
||||||
@ -25,6 +25,7 @@ def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enable
|
|||||||
target = symdef # type: ignore
|
target = symdef # type: ignore
|
||||||
else:
|
else:
|
||||||
raise CodeError("cannot incr/decr this", symdef)
|
raise CodeError("cannot incr/decr this", symdef)
|
||||||
|
|
||||||
if stmt.howmuch > 255:
|
if stmt.howmuch > 255:
|
||||||
if datatype_of(target, scope) != DataType.FLOAT:
|
if datatype_of(target, scope) != DataType.FLOAT:
|
||||||
raise CodeError("only supports integer incr/decr by up to 255 for now")
|
raise CodeError("only supports integer incr/decr by up to 255 for now")
|
||||||
@ -212,13 +213,65 @@ def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enable
|
|||||||
raise CodeError("cannot in/decrement memory of type " + str(target.datatype), stmt.howmuch)
|
raise CodeError("cannot in/decrement memory of type " + str(target.datatype), stmt.howmuch)
|
||||||
|
|
||||||
elif isinstance(target, Dereference):
|
elif isinstance(target, Dereference):
|
||||||
|
if isinstance(target.operand, (LiteralValue, SymbolName)):
|
||||||
|
if isinstance(target.operand, LiteralValue):
|
||||||
|
what = to_hex(target.operand.value)
|
||||||
|
else:
|
||||||
|
symdef = target.my_scope().lookup(target.operand.name)
|
||||||
|
if isinstance(symdef, VarDef) and symdef.vartype == VarType.MEMORY:
|
||||||
|
what = to_hex(symdef.value.value) # type: ignore
|
||||||
|
else:
|
||||||
|
what = target.operand.name
|
||||||
|
if stmt.howmuch == 1:
|
||||||
|
if target.datatype == DataType.FLOAT:
|
||||||
|
if not floats_enabled:
|
||||||
|
raise CodeError("floating point numbers not enabled via option")
|
||||||
|
with preserving_registers({'A', 'X', 'Y'}, scope, out, loads_a_within=True):
|
||||||
|
out("\vldx " + what)
|
||||||
|
out("\vldy {:s}+1".format(what))
|
||||||
|
if stmt.operator == "++":
|
||||||
|
out("\vjsr c64flt.float_add_one")
|
||||||
|
else:
|
||||||
|
out("\vjsr c64flt.float_sub_one")
|
||||||
|
else:
|
||||||
|
with preserving_registers({'A', 'Y'}, scope, out, loads_a_within=True):
|
||||||
|
out("\vlda " + what)
|
||||||
|
out("\vsta c64.SCRATCH_ZPWORD1")
|
||||||
|
out("\vlda {:s}+1".format(what))
|
||||||
|
out("\vsta c64.SCRATCH_ZPWORD1+1")
|
||||||
if target.datatype == DataType.BYTE:
|
if target.datatype == DataType.BYTE:
|
||||||
pass # @todo
|
if stmt.operator == "++":
|
||||||
|
out("\vjsr il65_lib.incr_deref_byte")
|
||||||
|
else:
|
||||||
|
out("\vjsr il65_lib.decr_deref_byte")
|
||||||
elif target.datatype == DataType.WORD:
|
elif target.datatype == DataType.WORD:
|
||||||
pass # @todo
|
if stmt.operator == "++":
|
||||||
elif target.datatype == DataType.FLOAT:
|
out("\vjsr il65_lib.incr_deref_word")
|
||||||
pass # @todo
|
|
||||||
else:
|
else:
|
||||||
raise CodeError("cannot inc/decrement dereferenced " + str(target.datatype), stmt)
|
out("\vjsr il65_lib.decr_deref_word")
|
||||||
else:
|
else:
|
||||||
raise CodeError("cannot inc/decrement", target) # @todo support more such as [dereference]++
|
raise CodeError("cannot inc/decrement dereferenced literal of type " + str(target.datatype), stmt)
|
||||||
|
else:
|
||||||
|
raise CodeError("can't inc/dec this by something else as 1 right now", stmt) # XXX
|
||||||
|
elif isinstance(target.operand, Register):
|
||||||
|
if target.operand.datatype == DataType.BYTE:
|
||||||
|
raise CodeError("can't dereference just a single register, need combined register", target)
|
||||||
|
reg = target.operand.name
|
||||||
|
if stmt.howmuch == 1:
|
||||||
|
if stmt.operator == "++":
|
||||||
|
out("\vclc")
|
||||||
|
else:
|
||||||
|
out("\vsec")
|
||||||
|
if target.datatype == DataType.BYTE:
|
||||||
|
with preserving_registers({'A', 'Y'}, scope, out, loads_a_within=True):
|
||||||
|
out("\vjsr il65_lib.incrdecr_deref_byte_reg_" + reg)
|
||||||
|
else:
|
||||||
|
with preserving_registers({'A', 'Y'}, scope, out, loads_a_within=True):
|
||||||
|
out("\vjsr il65_lib.incrdecr_deref_word_reg_" + reg)
|
||||||
|
else:
|
||||||
|
raise CodeError("can't inc/dec this by something else as 1 right now", stmt) # XXX
|
||||||
|
else:
|
||||||
|
raise TypeError("invalid dereference target type", target)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise CodeError("cannot inc/decrement", target) # @todo support more
|
||||||
|
@ -167,6 +167,81 @@ _mod2b lda #0 ; self-modified
|
|||||||
_done rts
|
_done rts
|
||||||
|
|
||||||
|
|
||||||
|
; increments/decrements a byte referenced by indirect register pair by 1
|
||||||
|
; clobbers A/Y, Carry flag determines incr or decr
|
||||||
|
incrdecr_deref_byte_reg_AX
|
||||||
|
sta SCRATCH_ZPWORD1
|
||||||
|
stx SCRATCH_ZPWORD1+1
|
||||||
|
bcc incr_deref_byte
|
||||||
|
bcs decr_deref_byte
|
||||||
|
incrdecr_deref_byte_reg_AY
|
||||||
|
sta SCRATCH_ZPWORD1
|
||||||
|
sty SCRATCH_ZPWORD1+1
|
||||||
|
bcc incr_deref_byte
|
||||||
|
bcs decr_deref_byte
|
||||||
|
incrdecr_deref_byte_reg_XY
|
||||||
|
stx SCRATCH_ZPWORD1
|
||||||
|
sty SCRATCH_ZPWORD1+1
|
||||||
|
bcs decr_deref_byte
|
||||||
|
|
||||||
|
incr_deref_byte
|
||||||
|
ldy #0
|
||||||
|
lda (c64.SCRATCH_ZPWORD1), y
|
||||||
|
adc #1 ; carry's cleared already
|
||||||
|
sta (c64.SCRATCH_ZPWORD1), y
|
||||||
|
rts
|
||||||
|
decr_deref_byte
|
||||||
|
ldy #0
|
||||||
|
lda (c64.SCRATCH_ZPWORD1), y
|
||||||
|
sbc #1 ; carry's set already
|
||||||
|
sta (c64.SCRATCH_ZPWORD1), y
|
||||||
|
rts
|
||||||
|
|
||||||
|
; increments/decrements a word referenced by indirect register pair by 1
|
||||||
|
; clobbers A/Y, Carry flag determines incr or decr
|
||||||
|
incrdecr_deref_word_reg_AX
|
||||||
|
sta SCRATCH_ZPWORD1
|
||||||
|
stx SCRATCH_ZPWORD1+1
|
||||||
|
bcc incr_deref_word
|
||||||
|
bcs decr_deref_word
|
||||||
|
incrdecr_deref_word_reg_AY
|
||||||
|
sta SCRATCH_ZPWORD1
|
||||||
|
sty SCRATCH_ZPWORD1+1
|
||||||
|
bcc incr_deref_word
|
||||||
|
bcs decr_deref_word
|
||||||
|
incrdecr_deref_word_reg_XY
|
||||||
|
stx SCRATCH_ZPWORD1
|
||||||
|
sty SCRATCH_ZPWORD1+1
|
||||||
|
bcs decr_deref_word
|
||||||
|
|
||||||
|
incr_deref_word
|
||||||
|
ldy #0
|
||||||
|
lda (c64.SCRATCH_ZPWORD1), y
|
||||||
|
adc #1 ; carry's cleared already
|
||||||
|
sta (c64.SCRATCH_ZPWORD1), y
|
||||||
|
bcc +
|
||||||
|
iny
|
||||||
|
lda (c64.SCRATCH_ZPWORD1), y
|
||||||
|
adc #0 ; carry is set
|
||||||
|
sta (c64.SCRATCH_ZPWORD1), y
|
||||||
|
+ rts
|
||||||
|
|
||||||
|
decr_deref_word
|
||||||
|
ldy #0
|
||||||
|
lda (c64.SCRATCH_ZPWORD1), y
|
||||||
|
bne +
|
||||||
|
pha
|
||||||
|
iny
|
||||||
|
lda (c64.SCRATCH_ZPWORD1), y
|
||||||
|
sbc #1 ; carry's set already
|
||||||
|
sta (c64.SCRATCH_ZPWORD1), y
|
||||||
|
dey
|
||||||
|
pla
|
||||||
|
+ sec
|
||||||
|
sbc #1
|
||||||
|
sta (c64.SCRATCH_ZPWORD1), y
|
||||||
|
rts
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
%noreturn
|
%noreturn
|
||||||
|
28
todo.ill
28
todo.ill
@ -1,3 +1,4 @@
|
|||||||
|
%output basic
|
||||||
%import c64lib
|
%import c64lib
|
||||||
|
|
||||||
~ main {
|
~ main {
|
||||||
@ -8,6 +9,8 @@
|
|||||||
; var .float initfloat2 = -555.666 ; @todo constant-fold before semantic check / fix float parse?
|
; var .float initfloat2 = -555.666 ; @todo constant-fold before semantic check / fix float parse?
|
||||||
; var .text guess = '?' * 80 ; @todo constant-fold before semantic check
|
; var .text guess = '?' * 80 ; @todo constant-fold before semantic check
|
||||||
const .word border = $d020
|
const .word border = $d020
|
||||||
|
var .word border2 = $d020
|
||||||
|
memory screenm = $d021
|
||||||
|
|
||||||
start:
|
start:
|
||||||
; @todo float incrdecr/augassign
|
; @todo float incrdecr/augassign
|
||||||
@ -18,10 +21,27 @@ start:
|
|||||||
; flt += 1000.1
|
; flt += 1000.1
|
||||||
; flt *= 2.34
|
; flt *= 2.34
|
||||||
|
|
||||||
[border] ++; @todo suport incr/decr on deref constant
|
screenm ++
|
||||||
[$d020] ++ ; @todo suport incr/decr on deref memory
|
screenm ++
|
||||||
[XY] ++
|
border2 ++
|
||||||
[X] ++
|
border2 ++
|
||||||
|
screenm --
|
||||||
|
border2 --
|
||||||
|
|
||||||
|
[$55 .float] ++
|
||||||
|
[screenm .float]--
|
||||||
|
|
||||||
|
;[border] ++
|
||||||
|
;[border] ++
|
||||||
|
;[border] --
|
||||||
|
[$d020] ++
|
||||||
|
[$d020] ++
|
||||||
|
[$d020] --
|
||||||
|
;[border2] ++ ;@todo suport incr/decr on deref var WORD
|
||||||
|
;[border2] ++ ;@todo suport incr/decr on deref var WORD
|
||||||
|
;[border2] -- ;@todo suport incr/decr on deref var WORD
|
||||||
|
;[XY] ++
|
||||||
|
;[XY] --
|
||||||
|
|
||||||
return 44.123
|
return 44.123
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user