mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
incrdecr codegen
This commit is contained in:
parent
a560982b7e
commit
d18876ee70
@ -5,12 +5,12 @@ This is the assembly code generator (from the parse tree)
|
|||||||
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import math
|
import math
|
||||||
|
import attr
|
||||||
from typing import Set, Callable
|
from typing import Set, Callable
|
||||||
from ..datatypes import FLOAT_MAX_POSITIVE, FLOAT_MAX_NEGATIVE
|
from ..datatypes import FLOAT_MAX_POSITIVE, FLOAT_MAX_NEGATIVE
|
||||||
from ..plyparse import Scope
|
from ..plyparse import Scope, AstNode
|
||||||
from ..compile import Zeropage
|
from ..compile import Zeropage
|
||||||
|
|
||||||
|
|
||||||
@ -18,6 +18,14 @@ class CodeError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s(repr=False, cmp=False)
|
||||||
|
class Context:
|
||||||
|
out = attr.ib(type=Callable)
|
||||||
|
stmt = attr.ib(type=AstNode)
|
||||||
|
scope = attr.ib(type=Scope)
|
||||||
|
floats_enabled = attr.ib(type=bool)
|
||||||
|
|
||||||
|
|
||||||
def to_hex(number: int) -> str:
|
def to_hex(number: int) -> str:
|
||||||
# 0..15 -> "0".."15"
|
# 0..15 -> "0".."15"
|
||||||
# 16..255 -> "$10".."$ff"
|
# 16..255 -> "$10".."$ff"
|
||||||
|
@ -7,20 +7,24 @@ 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, Assignment, AugAssignment, Register, LiteralValue, SymbolName, VarDef
|
from ..plyparse import Scope, Assignment, AugAssignment, Register, LiteralValue, SymbolName, VarDef
|
||||||
from . import CodeError, preserving_registers, to_hex
|
from . import CodeError, preserving_registers, to_hex, Context
|
||||||
from ..datatypes import REGISTER_BYTES, REGISTER_WORDS, VarType, DataType
|
from ..datatypes import REGISTER_BYTES, VarType
|
||||||
from ..compile import Zeropage
|
from ..compile import Zeropage
|
||||||
|
|
||||||
|
|
||||||
def generate_assignment(out: Callable, stmt: Assignment, scope: Scope) -> None:
|
def generate_assignment(ctx: Context) -> None:
|
||||||
out("\v\t\t\t; " + stmt.lineref)
|
assert isinstance(ctx.stmt, Assignment)
|
||||||
out("\v; @todo assignment")
|
ctx.out("\v\t\t\t; " + ctx.stmt.lineref)
|
||||||
|
ctx.out("\v; @todo assignment")
|
||||||
# @todo assignment
|
# @todo assignment
|
||||||
|
|
||||||
|
|
||||||
def generate_aug_assignment(out: Callable, stmt: AugAssignment, scope: Scope) -> None:
|
def generate_aug_assignment(ctx: Context) -> None:
|
||||||
# for instance: value += 3 (value = 0-255 for now)
|
# for instance: value += 3 (value = 0-255 for now)
|
||||||
# left: Register, SymbolName, or Dereference. right: Expression/LiteralValue
|
# left: Register, SymbolName, or Dereference. right: Expression/LiteralValue
|
||||||
|
out = ctx.out
|
||||||
|
stmt = ctx.stmt
|
||||||
|
assert isinstance(stmt, AugAssignment)
|
||||||
out("\v\t\t\t; " + stmt.lineref)
|
out("\v\t\t\t; " + stmt.lineref)
|
||||||
lvalue = stmt.left
|
lvalue = stmt.left
|
||||||
rvalue = stmt.right
|
rvalue = stmt.right
|
||||||
@ -28,23 +32,23 @@ def generate_aug_assignment(out: Callable, stmt: AugAssignment, scope: Scope) ->
|
|||||||
if isinstance(rvalue, LiteralValue):
|
if isinstance(rvalue, LiteralValue):
|
||||||
if type(rvalue.value) is int:
|
if type(rvalue.value) is int:
|
||||||
if 0 <= rvalue.value <= 255:
|
if 0 <= rvalue.value <= 255:
|
||||||
_generate_aug_reg_constant_int(out, lvalue, stmt.operator, rvalue.value, "", scope)
|
_generate_aug_reg_constant_int(out, lvalue, stmt.operator, rvalue.value, "", ctx.scope)
|
||||||
else:
|
else:
|
||||||
raise CodeError("aug. assignment value must be 0..255", rvalue)
|
raise CodeError("aug. assignment value must be 0..255", rvalue)
|
||||||
else:
|
else:
|
||||||
raise CodeError("constant integer literal or variable required for now", rvalue) # XXX
|
raise CodeError("constant integer literal or variable required for now", rvalue) # XXX
|
||||||
elif isinstance(rvalue, SymbolName):
|
elif isinstance(rvalue, SymbolName):
|
||||||
symdef = scope.lookup(rvalue.name)
|
symdef = ctx.scope.lookup(rvalue.name)
|
||||||
if isinstance(symdef, VarDef) and symdef.vartype == VarType.CONST and symdef.datatype.isinteger():
|
if isinstance(symdef, VarDef) and symdef.vartype == VarType.CONST and symdef.datatype.isinteger():
|
||||||
if 0 <= symdef.value.const_value() <= 255: # type: ignore
|
if 0 <= symdef.value.const_value() <= 255: # type: ignore
|
||||||
_generate_aug_reg_constant_int(out, lvalue, stmt.operator, 0, symdef.name, scope)
|
_generate_aug_reg_constant_int(out, lvalue, stmt.operator, 0, symdef.name, ctx.scope)
|
||||||
else:
|
else:
|
||||||
raise CodeError("aug. assignment value must be 0..255", rvalue)
|
raise CodeError("aug. assignment value must be 0..255", rvalue)
|
||||||
else:
|
else:
|
||||||
raise CodeError("constant integer literal or variable required for now", rvalue) # XXX
|
raise CodeError("constant integer literal or variable required for now", rvalue) # XXX
|
||||||
elif isinstance(rvalue, Register):
|
elif isinstance(rvalue, Register):
|
||||||
# @todo check value range (single register; 0-255) @todo support combined registers
|
# @todo check value range (single register; 0-255) @todo support combined registers
|
||||||
_generate_aug_reg_reg(out, lvalue, stmt.operator, rvalue, scope)
|
_generate_aug_reg_reg(out, lvalue, stmt.operator, rvalue, ctx.scope)
|
||||||
else:
|
else:
|
||||||
# @todo Register += symbolname / dereference , _generate_aug_reg_mem?
|
# @todo Register += symbolname / dereference , _generate_aug_reg_mem?
|
||||||
raise CodeError("invalid rvalue for aug. assignment on register", rvalue)
|
raise CodeError("invalid rvalue for aug. assignment on register", rvalue)
|
||||||
|
@ -5,13 +5,17 @@ This is the code generator for gotos and subroutine calls.
|
|||||||
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Callable
|
|
||||||
from ..plyparse import Goto, SubCall
|
from ..plyparse import Goto, SubCall
|
||||||
|
from . import Context
|
||||||
|
|
||||||
|
|
||||||
def generate_goto(out: Callable, stmt: Goto) -> None:
|
def generate_goto(ctx: Context) -> None:
|
||||||
|
stmt = ctx.stmt
|
||||||
|
assert isinstance(stmt, Goto)
|
||||||
pass # @todo
|
pass # @todo
|
||||||
|
|
||||||
|
|
||||||
def generate_subcall(out: Callable, stmt: SubCall) -> None:
|
def generate_subcall(ctx: Context) -> None:
|
||||||
|
stmt = ctx.stmt
|
||||||
|
assert isinstance(stmt, SubCall)
|
||||||
pass # @todo
|
pass # @todo
|
||||||
|
@ -11,7 +11,7 @@ from typing import TextIO, Callable, no_type_check
|
|||||||
from ..plylex import print_bold
|
from ..plylex import print_bold
|
||||||
from ..plyparse import Module, Scope, ProgramFormat, Block, Directive, VarDef, Label, Subroutine, AstNode, ZpOptions, \
|
from ..plyparse import Module, Scope, ProgramFormat, Block, Directive, VarDef, Label, Subroutine, AstNode, ZpOptions, \
|
||||||
InlineAssembly, Return, Register, Goto, SubCall, Assignment, AugAssignment, IncrDecr, AssignmentTargets
|
InlineAssembly, Return, Register, Goto, SubCall, Assignment, AugAssignment, IncrDecr, AssignmentTargets
|
||||||
from . import CodeError, to_hex, to_mflpt5
|
from . import CodeError, to_hex, to_mflpt5, Context
|
||||||
from .variables import generate_block_init, generate_block_vars
|
from .variables import generate_block_init, generate_block_vars
|
||||||
from .assignment import generate_assignment, generate_aug_assignment
|
from .assignment import generate_assignment, generate_aug_assignment
|
||||||
from .calls import generate_goto, generate_subcall
|
from .calls import generate_goto, generate_subcall
|
||||||
@ -131,6 +131,7 @@ class AssemblyGenerator:
|
|||||||
# there's no code in the zero page block.
|
# there's no code in the zero page block.
|
||||||
out("\v.pend\n")
|
out("\v.pend\n")
|
||||||
for block in sorted(self.module.all_nodes(Block), key=lambda b: b.address or 0):
|
for block in sorted(self.module.all_nodes(Block), key=lambda b: b.address or 0):
|
||||||
|
ctx = Context(out=out, stmt=None, scope=block.scope, floats_enabled=self.floats_enabled)
|
||||||
if block.name == "ZP":
|
if block.name == "ZP":
|
||||||
continue # already processed
|
continue # already processed
|
||||||
self.cur_block = block
|
self.cur_block = block
|
||||||
@ -153,7 +154,8 @@ class AssemblyGenerator:
|
|||||||
for stmt in block.scope.nodes:
|
for stmt in block.scope.nodes:
|
||||||
if isinstance(stmt, (VarDef, Subroutine)):
|
if isinstance(stmt, (VarDef, Subroutine)):
|
||||||
continue # should have been handled already or will be later
|
continue # should have been handled already or will be later
|
||||||
self.generate_statement(out, stmt, block.scope)
|
ctx.stmt = stmt
|
||||||
|
self.generate_statement(ctx)
|
||||||
if block.name == "main" and isinstance(stmt, Label) and stmt.name == "start":
|
if block.name == "main" and isinstance(stmt, Label) and stmt.name == "start":
|
||||||
# make sure the main.start routine clears the decimal and carry flags as first steps
|
# make sure the main.start routine clears the decimal and carry flags as first steps
|
||||||
out("\vcld\n\vclc\n\vclv")
|
out("\vcld\n\vclc\n\vclv")
|
||||||
@ -170,8 +172,8 @@ class AssemblyGenerator:
|
|||||||
out("\v; params: {}\n\v; returns: {} clobbers: {}".format(params or "-", returns or "-", clobbers or "-"))
|
out("\v; params: {}\n\v; returns: {} clobbers: {}".format(params or "-", returns or "-", clobbers or "-"))
|
||||||
cur_block = self.cur_block
|
cur_block = self.cur_block
|
||||||
self.cur_block = subdef.scope
|
self.cur_block = subdef.scope
|
||||||
for stmt in subdef.scope.nodes:
|
for ctx.stmt in subdef.scope.nodes:
|
||||||
self.generate_statement(out, stmt, subdef.scope)
|
self.generate_statement(ctx)
|
||||||
self.cur_block = cur_block
|
self.cur_block = cur_block
|
||||||
out("")
|
out("")
|
||||||
out("; -- end block subroutines")
|
out("; -- end block subroutines")
|
||||||
@ -185,48 +187,52 @@ class AssemblyGenerator:
|
|||||||
out("\n\v.pend\n")
|
out("\n\v.pend\n")
|
||||||
|
|
||||||
@no_type_check
|
@no_type_check
|
||||||
def generate_statement(self, out: Callable, stmt: AstNode, scope: Scope) -> None:
|
def generate_statement(self, ctx: Context) -> None:
|
||||||
|
stmt = ctx.stmt
|
||||||
if isinstance(stmt, Label):
|
if isinstance(stmt, Label):
|
||||||
out("\n{:s}\v\t\t; {:s}".format(stmt.name, stmt.lineref))
|
ctx.out("\n{:s}\v\t\t; {:s}".format(stmt.name, stmt.lineref))
|
||||||
elif isinstance(stmt, Return):
|
elif isinstance(stmt, Return):
|
||||||
if stmt.value_A:
|
if stmt.value_A:
|
||||||
reg = Register(name="A", sourceref=stmt.sourceref)
|
reg = Register(name="A", sourceref=stmt.sourceref)
|
||||||
assignment = Assignment(sourceref=stmt.sourceref)
|
assignment = Assignment(sourceref=stmt.sourceref)
|
||||||
assignment.nodes.append(AssignmentTargets(nodes=[reg], sourceref=stmt.sourceref))
|
assignment.nodes.append(AssignmentTargets(nodes=[reg], sourceref=stmt.sourceref))
|
||||||
assignment.nodes.append(stmt.value_A)
|
assignment.nodes.append(stmt.value_A)
|
||||||
generate_assignment(out, assignment, scope)
|
ctx.stmt = assignment
|
||||||
|
generate_assignment(ctx)
|
||||||
if stmt.value_X:
|
if stmt.value_X:
|
||||||
reg = Register(name="X", sourceref=stmt.sourceref)
|
reg = Register(name="X", sourceref=stmt.sourceref)
|
||||||
assignment = Assignment(sourceref=stmt.sourceref)
|
assignment = Assignment(sourceref=stmt.sourceref)
|
||||||
assignment.nodes.append(AssignmentTargets(nodes=[reg], sourceref=stmt.sourceref))
|
assignment.nodes.append(AssignmentTargets(nodes=[reg], sourceref=stmt.sourceref))
|
||||||
assignment.nodes.append(stmt.value_X)
|
assignment.nodes.append(stmt.value_X)
|
||||||
generate_assignment(out, assignment, scope)
|
ctx.stmt = assignment
|
||||||
|
generate_assignment(ctx)
|
||||||
if stmt.value_Y:
|
if stmt.value_Y:
|
||||||
reg = Register(name="Y", sourceref=stmt.sourceref)
|
reg = Register(name="Y", sourceref=stmt.sourceref)
|
||||||
assignment = Assignment(sourceref=stmt.sourceref)
|
assignment = Assignment(sourceref=stmt.sourceref)
|
||||||
assignment.nodes.append(AssignmentTargets(nodes=[reg], sourceref=stmt.sourceref))
|
assignment.nodes.append(AssignmentTargets(nodes=[reg], sourceref=stmt.sourceref))
|
||||||
assignment.nodes.append(stmt.value_Y)
|
assignment.nodes.append(stmt.value_Y)
|
||||||
generate_assignment(out, assignment, scope)
|
ctx.stmt = assignment
|
||||||
out("\vrts")
|
generate_assignment(ctx)
|
||||||
|
ctx.out("\vrts")
|
||||||
elif isinstance(stmt, InlineAssembly):
|
elif isinstance(stmt, InlineAssembly):
|
||||||
out("\n\v; inline asm, " + stmt.lineref)
|
ctx.out("\n\v; inline asm, " + stmt.lineref)
|
||||||
out(stmt.assembly)
|
ctx.out(stmt.assembly)
|
||||||
out("\v; end inline asm, " + stmt.lineref + "\n")
|
ctx.out("\v; end inline asm, " + stmt.lineref + "\n")
|
||||||
elif isinstance(stmt, IncrDecr):
|
elif isinstance(stmt, IncrDecr):
|
||||||
generate_incrdecr(out, stmt, scope, self.floats_enabled)
|
generate_incrdecr(ctx)
|
||||||
elif isinstance(stmt, Goto):
|
elif isinstance(stmt, Goto):
|
||||||
generate_goto(out, stmt)
|
generate_goto(ctx)
|
||||||
elif isinstance(stmt, SubCall):
|
elif isinstance(stmt, SubCall):
|
||||||
generate_subcall(out, stmt)
|
generate_subcall(ctx)
|
||||||
elif isinstance(stmt, Assignment):
|
elif isinstance(stmt, Assignment):
|
||||||
generate_assignment(out, stmt, scope)
|
generate_assignment(ctx)
|
||||||
elif isinstance(stmt, AugAssignment):
|
elif isinstance(stmt, AugAssignment):
|
||||||
generate_aug_assignment(out, stmt, scope)
|
generate_aug_assignment(ctx)
|
||||||
elif isinstance(stmt, Directive):
|
elif isinstance(stmt, Directive):
|
||||||
if stmt.name == "breakpoint":
|
if stmt.name == "breakpoint":
|
||||||
# put a marker in the source so that we can generate a list of breakpoints later
|
# put a marker in the source so that we can generate a list of breakpoints later
|
||||||
# this label is later extracted from the label dump file to turn it into a breakpoint instruction
|
# this label is later extracted from the label dump file to turn it into a breakpoint instruction
|
||||||
out("_il65_breakpoint_{:d}".format(id(stmt)))
|
ctx.out("_il65_breakpoint_{:d}".format(id(stmt)))
|
||||||
# other directives are ignored here
|
# other directives are ignored here
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("statement", stmt)
|
raise NotImplementedError("statement", stmt)
|
||||||
|
@ -7,13 +7,16 @@ is quite frequent and this generates assembly code tweaked for this case.
|
|||||||
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Callable
|
from ..plyparse import VarType, VarDef, Register, IncrDecr, SymbolName, Dereference, LiteralValue, 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, to_hex
|
from . import CodeError, preserving_registers, to_hex, Context
|
||||||
|
|
||||||
|
|
||||||
def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enabled: bool) -> None:
|
def generate_incrdecr(ctx: Context) -> None:
|
||||||
|
out = ctx.out
|
||||||
|
stmt = ctx.stmt
|
||||||
|
scope = ctx.scope
|
||||||
|
assert isinstance(stmt, IncrDecr)
|
||||||
assert isinstance(stmt.howmuch, (int, float)) and stmt.howmuch >= 0
|
assert isinstance(stmt.howmuch, (int, float)) and stmt.howmuch >= 0
|
||||||
assert stmt.operator in ("++", "--")
|
assert stmt.operator in ("++", "--")
|
||||||
if stmt.howmuch == 0:
|
if stmt.howmuch == 0:
|
||||||
@ -185,7 +188,7 @@ def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enable
|
|||||||
out("\vdec {:s}+1".format(what_str))
|
out("\vdec {:s}+1".format(what_str))
|
||||||
out("+")
|
out("+")
|
||||||
elif target.datatype == DataType.FLOAT:
|
elif target.datatype == DataType.FLOAT:
|
||||||
if not floats_enabled:
|
if not ctx.floats_enabled:
|
||||||
raise CodeError("floating point numbers not enabled via option")
|
raise CodeError("floating point numbers not enabled via option")
|
||||||
if stmt.howmuch == 1.0:
|
if stmt.howmuch == 1.0:
|
||||||
# special case for +/-1
|
# special case for +/-1
|
||||||
@ -224,7 +227,7 @@ def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enable
|
|||||||
what = target.operand.name
|
what = target.operand.name
|
||||||
if stmt.howmuch == 1:
|
if stmt.howmuch == 1:
|
||||||
if target.datatype == DataType.FLOAT:
|
if target.datatype == DataType.FLOAT:
|
||||||
if not floats_enabled:
|
if not ctx.floats_enabled:
|
||||||
raise CodeError("floating point numbers not enabled via option")
|
raise CodeError("floating point numbers not enabled via option")
|
||||||
with preserving_registers({'A', 'X', 'Y'}, scope, out, loads_a_within=True):
|
with preserving_registers({'A', 'X', 'Y'}, scope, out, loads_a_within=True):
|
||||||
out("\vldx " + what)
|
out("\vldx " + what)
|
||||||
@ -236,19 +239,13 @@ def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enable
|
|||||||
else:
|
else:
|
||||||
with preserving_registers({'A', 'Y'}, scope, out, loads_a_within=True):
|
with preserving_registers({'A', 'Y'}, scope, out, loads_a_within=True):
|
||||||
out("\vlda " + what)
|
out("\vlda " + what)
|
||||||
out("\vsta c64.SCRATCH_ZPWORD1")
|
out("\vldy {:s}+1".format(what))
|
||||||
out("\vlda {:s}+1".format(what))
|
|
||||||
out("\vsta c64.SCRATCH_ZPWORD1+1")
|
|
||||||
if target.datatype == DataType.BYTE:
|
if target.datatype == DataType.BYTE:
|
||||||
if stmt.operator == "++":
|
out("\vclc" if stmt.operator == "++" else "\vsec")
|
||||||
out("\vjsr il65_lib.incr_deref_byte")
|
out("\vjsr il65_lib.incrdecr_deref_byte_reg_AY")
|
||||||
else:
|
|
||||||
out("\vjsr il65_lib.decr_deref_byte")
|
|
||||||
elif target.datatype == DataType.WORD:
|
elif target.datatype == DataType.WORD:
|
||||||
if stmt.operator == "++":
|
out("\vclc" if stmt.operator == "++" else "\vsec")
|
||||||
out("\vjsr il65_lib.incr_deref_word")
|
out("\vjsr il65_lib.incrdecr_deref_word_reg_AY")
|
||||||
else:
|
|
||||||
out("\vjsr il65_lib.decr_deref_word")
|
|
||||||
else:
|
else:
|
||||||
raise CodeError("cannot inc/decrement dereferenced literal of type " + str(target.datatype), stmt)
|
raise CodeError("cannot inc/decrement dereferenced literal of type " + str(target.datatype), stmt)
|
||||||
else:
|
else:
|
||||||
@ -258,10 +255,7 @@ def generate_incrdecr(out: Callable, stmt: IncrDecr, scope: Scope, floats_enable
|
|||||||
raise CodeError("can't dereference just a single register, need combined register", target)
|
raise CodeError("can't dereference just a single register, need combined register", target)
|
||||||
reg = target.operand.name
|
reg = target.operand.name
|
||||||
if stmt.howmuch == 1:
|
if stmt.howmuch == 1:
|
||||||
if stmt.operator == "++":
|
out("\vclc" if stmt.operator == "++" else "\vsec")
|
||||||
out("\vclc")
|
|
||||||
else:
|
|
||||||
out("\vsec")
|
|
||||||
if target.datatype == DataType.BYTE:
|
if target.datatype == DataType.BYTE:
|
||||||
with preserving_registers({'A', 'Y'}, scope, out, loads_a_within=True):
|
with preserving_registers({'A', 'Y'}, scope, out, loads_a_within=True):
|
||||||
out("\vjsr il65_lib.incrdecr_deref_byte_reg_" + reg)
|
out("\vjsr il65_lib.incrdecr_deref_byte_reg_" + reg)
|
||||||
|
15
todo.ill
15
todo.ill
@ -31,17 +31,16 @@ start:
|
|||||||
[$55 .float] ++
|
[$55 .float] ++
|
||||||
[screenm .float]--
|
[screenm .float]--
|
||||||
|
|
||||||
;[border] ++
|
[border] ++
|
||||||
;[border] ++
|
[border] ++
|
||||||
;[border] --
|
[border] --
|
||||||
[$d020] ++
|
[$d020] ++
|
||||||
[$d020] ++
|
[$d020] ++
|
||||||
[$d020] --
|
[$d020] --
|
||||||
;[border2] ++ ;@todo suport incr/decr on deref var WORD
|
[border2 .word] ++
|
||||||
;[border2] ++ ;@todo suport incr/decr on deref var WORD
|
[border2 .float] ++
|
||||||
;[border2] -- ;@todo suport incr/decr on deref var WORD
|
[border2] --
|
||||||
;[XY] ++
|
[XY] ++
|
||||||
;[XY] --
|
|
||||||
|
|
||||||
return 44.123
|
return 44.123
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user