mirror of
https://github.com/irmen/prog8.git
synced 2025-02-27 18:29:00 +00:00
incrdecr codegen
This commit is contained in:
parent
76755cf57d
commit
a560982b7e
@ -83,7 +83,6 @@ class PlyParser:
|
||||
if node.datatype == DataType.FLOAT:
|
||||
raise ParseError("floating point numbers not enabled via option", node.sourceref)
|
||||
|
||||
|
||||
def coerce_values(self, module: Module) -> None:
|
||||
for node in module.all_nodes():
|
||||
try:
|
||||
@ -182,6 +181,9 @@ class PlyParser:
|
||||
elif isinstance(node, VarDef):
|
||||
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)
|
||||
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
|
||||
|
||||
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 ..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 . import CodeError, preserving_registers
|
||||
from . import CodeError, preserving_registers, to_hex
|
||||
|
||||
|
||||
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
|
||||
else:
|
||||
raise CodeError("cannot incr/decr this", symdef)
|
||||
|
||||
if stmt.howmuch > 255:
|
||||
if datatype_of(target, scope) != DataType.FLOAT:
|
||||
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)
|
||||
|
||||
elif isinstance(target, Dereference):
|
||||
if target.datatype == DataType.BYTE:
|
||||
pass # @todo
|
||||
elif target.datatype == DataType.WORD:
|
||||
pass # @todo
|
||||
elif target.datatype == DataType.FLOAT:
|
||||
pass # @todo
|
||||
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 stmt.operator == "++":
|
||||
out("\vjsr il65_lib.incr_deref_byte")
|
||||
else:
|
||||
out("\vjsr il65_lib.decr_deref_byte")
|
||||
elif target.datatype == DataType.WORD:
|
||||
if stmt.operator == "++":
|
||||
out("\vjsr il65_lib.incr_deref_word")
|
||||
else:
|
||||
out("\vjsr il65_lib.decr_deref_word")
|
||||
else:
|
||||
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 CodeError("cannot inc/decrement dereferenced " + str(target.datatype), stmt)
|
||||
raise TypeError("invalid dereference target type", target)
|
||||
|
||||
else:
|
||||
raise CodeError("cannot inc/decrement", target) # @todo support more such as [dereference]++
|
||||
raise CodeError("cannot inc/decrement", target) # @todo support more
|
||||
|
@ -167,6 +167,81 @@ _mod2b lda #0 ; self-modified
|
||||
_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
|
||||
|
28
todo.ill
28
todo.ill
@ -1,3 +1,4 @@
|
||||
%output basic
|
||||
%import c64lib
|
||||
|
||||
~ main {
|
||||
@ -8,6 +9,8 @@
|
||||
; var .float initfloat2 = -555.666 ; @todo constant-fold before semantic check / fix float parse?
|
||||
; var .text guess = '?' * 80 ; @todo constant-fold before semantic check
|
||||
const .word border = $d020
|
||||
var .word border2 = $d020
|
||||
memory screenm = $d021
|
||||
|
||||
start:
|
||||
; @todo float incrdecr/augassign
|
||||
@ -18,10 +21,27 @@ start:
|
||||
; flt += 1000.1
|
||||
; flt *= 2.34
|
||||
|
||||
[border] ++; @todo suport incr/decr on deref constant
|
||||
[$d020] ++ ; @todo suport incr/decr on deref memory
|
||||
[XY] ++
|
||||
[X] ++
|
||||
screenm ++
|
||||
screenm ++
|
||||
border2 ++
|
||||
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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user