mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
var inits
This commit is contained in:
parent
1df28c8091
commit
7218c17689
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,3 +17,4 @@
|
||||
__pycache__/
|
||||
parser.out
|
||||
parsetab.py
|
||||
!/il65/lib/*
|
||||
|
@ -16,7 +16,7 @@ from .plyparse import parse_file, ParseError, Module, Directive, Block, Subrouti
|
||||
SymbolName, Dereference, AddressOf
|
||||
from .plylex import SourceRef, print_bold
|
||||
from .optimize import optimize
|
||||
from .datatypes import DataType, datatype_sizes
|
||||
from .datatypes import DataType, STRING_DATATYPES
|
||||
|
||||
|
||||
class CompileError(Exception):
|
||||
@ -86,7 +86,7 @@ class PlyParser:
|
||||
zeropage = Zeropage(module.zp_options)
|
||||
for vardef in zpnode.scope.filter_nodes(VarDef):
|
||||
try:
|
||||
vardef.zp_address = zeropage.allocate(vardef.name, vardef.datatype)
|
||||
vardef.zp_address = zeropage.allocate(vardef)
|
||||
except CompileError as x:
|
||||
raise ParseError(str(x), vardef.sourceref)
|
||||
|
||||
@ -108,7 +108,6 @@ class PlyParser:
|
||||
except Exception as x:
|
||||
self.handle_internal_error(x, "process_expressions of node {} in block {}".format(node, block.name))
|
||||
|
||||
@no_type_check
|
||||
def create_multiassigns(self, module: Module) -> None:
|
||||
# create multi-assign statements from nested assignments (A=B=C=5),
|
||||
# and optimize TargetRegisters down to single Register if it's just one register.
|
||||
@ -120,7 +119,7 @@ class PlyParser:
|
||||
return assign
|
||||
|
||||
for block, parent in module.all_scopes():
|
||||
for node in block.nodes:
|
||||
for node in block.nodes: # type: ignore
|
||||
if isinstance(node, Assignment):
|
||||
if isinstance(node.right, Assignment):
|
||||
multi = reduce_right(node)
|
||||
@ -428,8 +427,8 @@ class Zeropage:
|
||||
assert self.SCRATCH_W1 not in self.free
|
||||
assert self.SCRATCH_W2 not in self.free
|
||||
|
||||
def allocate(self, name: str, datatype: DataType) -> int:
|
||||
assert not name or name not in {a[0] for a in self.allocations.values()}, "var name is not unique"
|
||||
def allocate(self, vardef: VarDef) -> int:
|
||||
assert not vardef.name or vardef.name not in {a[0] for a in self.allocations.values()}, "var name is not unique"
|
||||
|
||||
def sequential_free(location: int) -> bool:
|
||||
return all(location + i in self.free for i in range(size))
|
||||
@ -440,10 +439,30 @@ class Zeropage:
|
||||
def make_allocation(location: int) -> int:
|
||||
for loc in range(location, location + size):
|
||||
self.free.remove(loc)
|
||||
self.allocations[location] = (name or "<unnamed>", datatype)
|
||||
self.allocations[location] = (vardef.name or "<unnamed>", vardef.datatype)
|
||||
return location
|
||||
|
||||
size = datatype_sizes[datatype]
|
||||
if vardef.datatype == DataType.BYTE:
|
||||
size = 1
|
||||
elif vardef.datatype == DataType.WORD:
|
||||
size = 2
|
||||
elif vardef.datatype == DataType.FLOAT:
|
||||
print_bold("warning: {}: allocating a large datatype in zeropage".format(vardef.sourceref))
|
||||
size = 5
|
||||
elif vardef.datatype == DataType.BYTEARRAY:
|
||||
print_bold("warning: {}: allocating a large datatype in zeropage".format(vardef.sourceref))
|
||||
size = vardef.size[0]
|
||||
elif vardef.datatype == DataType.WORDARRAY:
|
||||
print_bold("warning: {}: allocating a large datatype in zeropage".format(vardef.sourceref))
|
||||
size = vardef.size[0] * 2
|
||||
elif vardef.datatype == DataType.MATRIX:
|
||||
print_bold("warning: {}: allocating a large datatype in zeropage".format(vardef.sourceref))
|
||||
size = vardef.size[0] * vardef.size[1]
|
||||
elif vardef.datatype in STRING_DATATYPES:
|
||||
print_bold("warning: {}: allocating a large datatype in zeropage".format(vardef.sourceref))
|
||||
size = vardef.size[0]
|
||||
else:
|
||||
raise CompileError("cannot put datatype {:s} in ZP".format(vardef.datatype.name))
|
||||
if len(self.free) > 0:
|
||||
if size == 1:
|
||||
for candidate in range(min(self.free), max(self.free)+1):
|
||||
|
@ -47,13 +47,6 @@ class DataType(enum.Enum):
|
||||
return NotImplemented
|
||||
|
||||
|
||||
datatype_sizes = {
|
||||
DataType.BYTE: 1,
|
||||
DataType.WORD: 2,
|
||||
DataType.FLOAT: 5
|
||||
}
|
||||
|
||||
|
||||
STRING_DATATYPES = {DataType.STRING, DataType.STRING_P, DataType.STRING_S, DataType.STRING_PS}
|
||||
|
||||
REGISTER_SYMBOLS = {"A", "X", "Y", "AX", "AY", "XY", "SC", "SI"}
|
||||
|
@ -5,6 +5,7 @@ This is the assembly code generator (from the parse tree)
|
||||
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import datetime
|
||||
@ -13,7 +14,7 @@ from typing import Dict, TextIO, List, Any
|
||||
from .plylex import print_bold
|
||||
from .plyparse import Module, ProgramFormat, Block, Directive, VarDef, Label, Subroutine, AstNode, ZpOptions, \
|
||||
InlineAssembly, Return, Register, LiteralValue
|
||||
from .datatypes import VarType, DataType, datatype_sizes, to_hex, mflpt5_to_float, to_mflpt5, STRING_DATATYPES
|
||||
from .datatypes import VarType, DataType, to_hex, to_mflpt5, STRING_DATATYPES
|
||||
|
||||
|
||||
class CodeError(Exception):
|
||||
@ -89,9 +90,9 @@ class AssemblyGenerator:
|
||||
self.p("* = " + to_hex(self.module.address))
|
||||
year = datetime.datetime.now().year
|
||||
self.p("\v.word (+), {:d}".format(year))
|
||||
self.p("\v.null $9e, format(' %d ', _il65_sysaddr), $3a, $8f, ' il65 by idj'")
|
||||
self.p("\v.null $9e, format(' %d ', _il65_entrypoint), $3a, $8f, ' il65 by idj'")
|
||||
self.p("+\v.word 0")
|
||||
self.p("_il65_sysaddr\v; assembly code starts here\n")
|
||||
self.p("_il65_entrypoint\v; assembly code starts here\n")
|
||||
else:
|
||||
self.p("; ---- program without sys call ----")
|
||||
self.p("* = " + to_hex(self.module.address) + "\n")
|
||||
@ -101,7 +102,7 @@ class AssemblyGenerator:
|
||||
|
||||
def init_vars_and_start(self) -> None:
|
||||
if self.module.zp_options == ZpOptions.CLOBBER_RESTORE:
|
||||
self.p("\vjsr il65_lib_zp.save_zeropage")
|
||||
self.p("\vjsr _il65_save_zeropage")
|
||||
self.p("\v; initialize all blocks (reset vars)")
|
||||
if self.module.zeropage():
|
||||
self.p("\vjsr ZP._il65_init_block")
|
||||
@ -112,7 +113,12 @@ class AssemblyGenerator:
|
||||
if self.module.zp_options == ZpOptions.CLOBBER_RESTORE:
|
||||
self.p("\vjsr {:s}.start".format(self.module.main().label))
|
||||
self.p("\vcld")
|
||||
self.p("\vjmp il65_lib_zp.restore_zeropage")
|
||||
self.p("\vjmp _il65_restore_zeropage\n")
|
||||
# include the assembly code for the save/restore zeropage routines
|
||||
zprestorefile = os.path.join(os.path.split(__file__)[0], "lib", "restorezp.asm")
|
||||
with open(zprestorefile, "rU") as f:
|
||||
for line in f.readlines():
|
||||
self.p(line.rstrip("\n"))
|
||||
else:
|
||||
self.p("\vjmp {:s}.start".format(self.module.main().label))
|
||||
self.p("")
|
||||
@ -215,41 +221,61 @@ class AssemblyGenerator:
|
||||
def generate_block_init(self, block: Block) -> None:
|
||||
# generate the block initializer
|
||||
# @todo add a block initializer subroutine that can contain custom reset/init code? (static initializer)
|
||||
|
||||
def _memset(varname: str, value: int, size: int) -> None:
|
||||
value = value or 0
|
||||
self.p("\vlda #<" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1")
|
||||
self.p("\vlda #>" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1+1")
|
||||
self.p("\vlda #" + to_hex(value))
|
||||
self.p("\vldx #" + to_hex(size))
|
||||
self.p("\vjsr il65_lib.memset")
|
||||
|
||||
def _memsetw(varname: str, value: int, size: int) -> None:
|
||||
value = value or 0
|
||||
self.p("\vlda #<" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1")
|
||||
self.p("\vlda #>" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1+1")
|
||||
self.p("\vlda #<" + to_hex(value))
|
||||
self.p("\vldy #>" + to_hex(value))
|
||||
self.p("\vldx #" + to_hex(size))
|
||||
self.p("\vjsr il65_lib.memsetw")
|
||||
|
||||
self.p("_il65_init_block\v; (re)set vars to initial values")
|
||||
self.p("\vlda #0\n\vldx #0")
|
||||
float_inits = {}
|
||||
string_inits = []
|
||||
prev_value = 0
|
||||
vardefs = [vd for vd in block.scope.filter_nodes(VarDef) if vd.vartype == VarType.VAR]
|
||||
# @todo optimize init order (sort on value first to avoid needless register loads, etc)
|
||||
for variable in vardefs:
|
||||
vname = variable.name
|
||||
vvalue = variable.value
|
||||
if variable.datatype == DataType.BYTE:
|
||||
if vvalue != prev_value:
|
||||
self.p("\vlda #${:02x}".format(vvalue))
|
||||
prev_value = vvalue
|
||||
self.p("\vsta {:s}".format(vname))
|
||||
elif variable.datatype == DataType.WORD:
|
||||
if vvalue != prev_value:
|
||||
self.p("\vlda #<${:04x}".format(vvalue))
|
||||
self.p("\vldx #>${:04x}".format(vvalue))
|
||||
prev_value = vvalue
|
||||
self.p("\vsta {:s}".format(vname))
|
||||
self.p("\vstx {:s}+1".format(vname))
|
||||
elif variable.datatype == DataType.FLOAT:
|
||||
fpbytes = to_mflpt5(vvalue) # type: ignore
|
||||
float_inits[variable.name] = (vname, fpbytes, vvalue)
|
||||
elif variable.datatype in STRING_DATATYPES:
|
||||
string_inits.append(variable)
|
||||
elif variable.datatype == DataType.BYTEARRAY:
|
||||
pass # @todo init bytearray
|
||||
elif variable.datatype == DataType.WORDARRAY:
|
||||
pass # @todo init wordarray
|
||||
elif variable.datatype == DataType.MATRIX:
|
||||
pass # @todo init matrix
|
||||
else:
|
||||
raise CodeError("weird var datatype", variable.datatype)
|
||||
prev_value_a, prev_value_x = None, None
|
||||
vars_by_datatype = defaultdict(list) # type: Dict[DataType, List[VarDef]]
|
||||
for vardef in block.scope.filter_nodes(VarDef):
|
||||
if vardef.vartype == VarType.VAR:
|
||||
vars_by_datatype[vardef.datatype].append(vardef)
|
||||
for bytevar in sorted(vars_by_datatype[DataType.BYTE], key=lambda vd: vd.value):
|
||||
if bytevar.value != prev_value_a:
|
||||
self.p("\vlda #${:02x}".format(bytevar.value))
|
||||
prev_value_a = bytevar.value
|
||||
self.p("\vsta {:s}".format(bytevar.name))
|
||||
for wordvar in sorted(vars_by_datatype[DataType.WORD], key=lambda vd: vd.value):
|
||||
v_hi, v_lo = divmod(wordvar.value, 256)
|
||||
if v_hi != prev_value_a:
|
||||
self.p("\vlda #${:02x}".format(v_hi))
|
||||
prev_value_a = v_hi
|
||||
if v_lo != prev_value_x:
|
||||
self.p("\vldx #${:02x}".format(v_lo))
|
||||
prev_value_x = v_lo
|
||||
self.p("\vsta {:s}".format(wordvar.name))
|
||||
self.p("\vstx {:s}+1".format(wordvar.name))
|
||||
for floatvar in vars_by_datatype[DataType.FLOAT]:
|
||||
fpbytes = to_mflpt5(floatvar.value) # type: ignore
|
||||
float_inits[floatvar.name] = (floatvar.name, fpbytes, floatvar.value)
|
||||
for arrayvar in vars_by_datatype[DataType.BYTEARRAY]:
|
||||
_memset(arrayvar.name, arrayvar.value, arrayvar.size[0])
|
||||
for arrayvar in vars_by_datatype[DataType.WORDARRAY]:
|
||||
_memsetw(arrayvar.name, arrayvar.value, arrayvar.size[0])
|
||||
for arrayvar in vars_by_datatype[DataType.MATRIX]:
|
||||
_memset(arrayvar.name, arrayvar.value, arrayvar.size[0] * arrayvar.size[1])
|
||||
# @todo string datatype inits with 1 memcopy
|
||||
if float_inits:
|
||||
self.p("\vldx #4")
|
||||
self.p("-")
|
||||
@ -258,8 +284,6 @@ class AssemblyGenerator:
|
||||
self.p("\vsta {:s},x".format(vname))
|
||||
self.p("\vdex")
|
||||
self.p("\vbpl -")
|
||||
if string_inits:
|
||||
pass # @todo init string block (1 memcopy)
|
||||
self.p("\vrts\n")
|
||||
for varname, (vname, fpbytes, fpvalue) in sorted(float_inits.items()):
|
||||
self.p("_init_float_{:s}\t\t.byte ${:02x}, ${:02x}, ${:02x}, ${:02x}, ${:02x}\t; {}".format(varname, *fpbytes, fpvalue))
|
||||
@ -324,8 +348,12 @@ class AssemblyGenerator:
|
||||
# zeropage uses the zp_address we've allocated, instead of allocating memory here
|
||||
for vardef in vars_by_vartype.get(VarType.VAR, []):
|
||||
assert vardef.zp_address is not None
|
||||
self.p("\v{:s} = {:s}\t; {:s} ({:d})".format(vardef.name, to_hex(vardef.zp_address),
|
||||
vardef.datatype.name.lower(), datatype_sizes[vardef.datatype]))
|
||||
if vardef.datatype in (DataType.WORDARRAY, DataType.BYTEARRAY, DataType.MATRIX):
|
||||
size_str = "size " + str(vardef.size)
|
||||
else:
|
||||
size_str = ""
|
||||
self.p("\v{:s} = {:s}\t; {:s} {:s}".format(vardef.name, to_hex(vardef.zp_address),
|
||||
vardef.datatype.name.lower(), size_str))
|
||||
else:
|
||||
# create definitions for the variables that takes up empty space and will be initialized at startup
|
||||
string_vars = []
|
||||
|
@ -1,58 +1,10 @@
|
||||
; IL65 internal library routines
|
||||
; IL65 internal library routines - always included by the compiler
|
||||
;
|
||||
; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
; ;
|
||||
;
|
||||
; indent format: TABS, size=8
|
||||
|
||||
|
||||
~ il65_lib_zp {
|
||||
; note: separate block so the 64tass assembler can remove this when no zp restore is required
|
||||
|
||||
%asm {
|
||||
|
||||
; ---- store the Zeropage in a backup area
|
||||
save_zeropage
|
||||
sei
|
||||
ldx #2
|
||||
- lda $00,x
|
||||
sta zp_backup,x
|
||||
inx
|
||||
bne -
|
||||
cli
|
||||
rts
|
||||
|
||||
restore_zeropage
|
||||
php
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
sei
|
||||
|
||||
lda $a0 ; save the current jiffy clock
|
||||
sta zp_backup+$a0
|
||||
lda $a1
|
||||
sta zp_backup+$a1
|
||||
lda $a2
|
||||
sta zp_backup+$a2
|
||||
|
||||
ldx #2
|
||||
- lda zp_backup-2,x
|
||||
sta $00,x
|
||||
inx
|
||||
bne -
|
||||
cli
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
plp
|
||||
rts
|
||||
|
||||
zp_backup .fill 256, 0
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
~ il65_lib {
|
||||
; note: the following ZP scratch registers must be the same as in c64lib
|
||||
memory .byte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
|
||||
@ -120,7 +72,7 @@ memcopy16_up
|
||||
rts ; done
|
||||
|
||||
|
||||
; copy memory UP from (SCRATCH_ZPWORD1) to (AY) with length X (0 = 256)
|
||||
; copy memory UP from (SCRATCH_ZPWORD1) to (AY) with length X (1 to 256, 0 meaning 256)
|
||||
; destination must not overlap, or be before start, then overlap is possible.
|
||||
; clobbers A, X, Y
|
||||
|
||||
@ -128,12 +80,37 @@ memcopy
|
||||
sta SCRATCH_ZPWORD2
|
||||
sty SCRATCH_ZPWORD2+1
|
||||
ldy #0
|
||||
- lda (SCRATCH_ZPWORD1),y
|
||||
sta (SCRATCH_ZPWORD2),y
|
||||
- lda (SCRATCH_ZPWORD1), y
|
||||
sta (SCRATCH_ZPWORD2), y
|
||||
iny
|
||||
dex
|
||||
bne -
|
||||
rts
|
||||
|
||||
|
||||
; fill memory from (SCRATCH_ZPWORD1) length X (1-256, 0=256) with value in A.
|
||||
; clobbers X, Y
|
||||
memset ldy #0
|
||||
- sta (SCRATCH_ZPWORD1), y
|
||||
iny
|
||||
dex
|
||||
bne -
|
||||
rts
|
||||
|
||||
; fill memory from (SCRATCH_ZPWORD1) length X (1-256, 0=256) with word value in AY.
|
||||
; clobbers A, X, Y
|
||||
memsetw sty _mod_hi+1 ; self-modify
|
||||
sta _mod_lo+1 ; self-modify
|
||||
ldy #0
|
||||
_mod_lo lda #$00 ; self-modified
|
||||
sta (SCRATCH_ZPWORD1), y
|
||||
iny
|
||||
_mod_hi lda #$00 ; self-modified
|
||||
sta (SCRATCH_ZPWORD1), y
|
||||
iny
|
||||
dex
|
||||
bne _mod_lo
|
||||
rts
|
||||
|
||||
}
|
||||
}
|
||||
|
43
il65/lib/restorezp.asm
Normal file
43
il65/lib/restorezp.asm
Normal file
@ -0,0 +1,43 @@
|
||||
; backup/restore the zero page
|
||||
; this is in a separate file so it can be omitted completely if it's not needed.
|
||||
|
||||
_il65_save_zeropage
|
||||
lda #%00101111
|
||||
sta _il65_zp_backup ; default value for $00
|
||||
lda #%00100111
|
||||
sta _il65_zp_backup+1 ; default value for $01
|
||||
ldx #2
|
||||
- lda $00,x
|
||||
sta _il65_zp_backup,x
|
||||
inx
|
||||
bne -
|
||||
rts
|
||||
|
||||
_il65_restore_zeropage
|
||||
php
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
sei
|
||||
|
||||
lda $a0 ; save the current jiffy clock
|
||||
sta _il65_zp_backup+$a0
|
||||
lda $a1
|
||||
sta _il65_zp_backup+$a1
|
||||
lda $a2
|
||||
sta _il65_zp_backup+$a2
|
||||
|
||||
ldx #0
|
||||
- lda _il65_zp_backup,x
|
||||
sta $00,x
|
||||
inx
|
||||
bne -
|
||||
cli
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
plp
|
||||
rts
|
||||
|
||||
_il65_zp_backup
|
||||
.fill 256
|
@ -402,7 +402,7 @@ class InlineAssembly(AstNode):
|
||||
assembly = attr.ib(type=str)
|
||||
|
||||
|
||||
@attr.s(cmp=False, repr=False, slots=True)
|
||||
@attr.s(cmp=False, repr=True, slots=True)
|
||||
class VarDef(AstNode):
|
||||
name = attr.ib(type=str)
|
||||
vartype = attr.ib()
|
||||
@ -430,6 +430,8 @@ class VarDef(AstNode):
|
||||
assert self.size is None
|
||||
self.size = self.datatype.dimensions or [1]
|
||||
self.datatype = self.datatype.to_enum()
|
||||
if self.datatype in {DataType.BYTEARRAY, DataType.WORDARRAY, DataType.MATRIX} and sum(self.size) in (0, 1):
|
||||
print("warning: {}: array/matrix with size 1, use normal byte/word instead for efficiency".format(self.sourceref))
|
||||
if self.vartype == VarType.CONST and self.value is None:
|
||||
raise ParseError("constant value assignment is missing",
|
||||
attr.evolve(self.sourceref, column=self.sourceref.column+len(self.name)))
|
||||
@ -446,7 +448,9 @@ class VarDef(AstNode):
|
||||
if self.vartype in (VarType.CONST, VarType.VAR):
|
||||
try:
|
||||
_, self.value = coerce_value(self.datatype, self.value, self.sourceref)
|
||||
except (TypeError, OverflowError) as x:
|
||||
except OverflowError as x:
|
||||
raise ParseError(str(x), self.sourceref) from None
|
||||
except TypeError as x:
|
||||
raise ParseError("processed expression vor vardef is not a constant value: " + str(x), self.sourceref) from None
|
||||
|
||||
|
||||
@ -679,11 +683,11 @@ def process_constant_expression(expr: Any, sourceref: SourceRef, symbolscope: Sc
|
||||
else:
|
||||
raise ExpressionEvaluationError("can only use math- or builtin function", expr.sourceref)
|
||||
elif isinstance(target, Dereference): # '[...](1,2,3)'
|
||||
return None # XXX
|
||||
raise NotImplementedError("dereferenced call") # XXX
|
||||
elif isinstance(target, int): # '64738()'
|
||||
return None # XXX
|
||||
raise NotImplementedError("immediate address call") # XXX
|
||||
else:
|
||||
raise NotImplementedError("weird call target", target) # XXX
|
||||
raise NotImplementedError("weird call target", target)
|
||||
else:
|
||||
raise ParseError("function name required, not {}".format(expr.target.__class__.__name__), expr.sourceref)
|
||||
elif not isinstance(expr, Expression):
|
||||
|
@ -116,7 +116,8 @@ The normal IRQ routine in the C-64's kernal will read and write several location
|
||||
|
||||
These locations will not be used by the compiler for zero page variables, so your variables will
|
||||
not interfere with the IRQ routine and vice versa. This is true for the normal zp mode but also
|
||||
for the mode where the whole zp has been taken over.
|
||||
for the mode where the whole zp has been taken over. So the normal IRQ vector is still
|
||||
running when your program is entered, even when you use ``%zp clobber``.
|
||||
|
||||
|
||||
@todo: some global way (in ZP block) to promote certian other blocks/variables from that block or even
|
||||
|
33
todo.ill
33
todo.ill
@ -1,4 +1,5 @@
|
||||
%output basic
|
||||
%zp clobber,restore
|
||||
|
||||
~ ZP {
|
||||
var zp1_1 = 200
|
||||
@ -15,6 +16,17 @@
|
||||
var zp2_2 = 100
|
||||
var .word zp2_3 = $55aa
|
||||
var .word zp2_4 = $66bb
|
||||
var .word zp2_5 = $66bc
|
||||
var .word zp2_6 = $66bd
|
||||
var .word zp2_7 = $66be
|
||||
var .word zp2_8 = $67be
|
||||
var .word zp2_9 = $68be
|
||||
var .word zp2_10 = $69be
|
||||
var .word zp2_11 = $69be
|
||||
var .array(4) array1
|
||||
var .wordarray(4) warray1
|
||||
var .matrix(3,3) matrix1
|
||||
var .text string = "bye"
|
||||
const .text zpc2_1 = "hello"
|
||||
const zpc2_2 = 0
|
||||
}
|
||||
@ -22,12 +34,31 @@
|
||||
|
||||
~ main {
|
||||
|
||||
var .text hello_str = "hello there"
|
||||
var .float float1 = 3.14
|
||||
var .float float2 = 3.14
|
||||
var .float float3 = 3.14
|
||||
var .float float4 = 3.14
|
||||
var .float float5 = 3.14
|
||||
var .array(10) array1
|
||||
var .wordarray(10) warray1
|
||||
var .matrix(4,4) matrix1
|
||||
var b1 = 10
|
||||
var b2 = 20
|
||||
var b3 = 10
|
||||
var b4 = 20
|
||||
var b5 = 10
|
||||
var b6 = 20
|
||||
var b7 = 10
|
||||
var b8 = 30
|
||||
var b9 = 30
|
||||
var b10 = 40
|
||||
var b11 = 40
|
||||
var b12 = 30
|
||||
var b13 = 40
|
||||
var b14 = 0
|
||||
var b15 = 0
|
||||
var b16 = 0
|
||||
|
||||
|
||||
start:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user