mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
restructure codegen
This commit is contained in:
parent
44c0d243ef
commit
4d929e00f5
1
il65/codegen/__init__.py
Normal file
1
il65/codegen/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# package
|
@ -1,21 +1,15 @@
|
||||
"""
|
||||
Programming Language for 6502/6510 microprocessors, codename 'Sick'
|
||||
This is the assembly code generator (from the parse tree)
|
||||
This is the 6502 assembly code generator (directly from the parse tree)
|
||||
|
||||
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
import math
|
||||
import attr
|
||||
from typing import Set, Callable, no_type_check
|
||||
from ..datatypes import FLOAT_MAX_POSITIVE, FLOAT_MAX_NEGATIVE
|
||||
from ..plyparse import Scope, AstNode
|
||||
from ..compile import Zeropage
|
||||
|
||||
|
||||
class CodeError(Exception):
|
||||
pass
|
||||
from typing import Set, Callable
|
||||
from ...plyparse import Scope, AstNode
|
||||
from ...compile import Zeropage
|
||||
|
||||
|
||||
@attr.s(repr=False, cmp=False)
|
||||
@ -26,56 +20,6 @@ class Context:
|
||||
floats_enabled = attr.ib(type=bool)
|
||||
|
||||
|
||||
def to_hex(number: int) -> str:
|
||||
# 0..15 -> "0".."15"
|
||||
# 16..255 -> "$10".."$ff"
|
||||
# 256..65536 -> "$0100".."$ffff"
|
||||
assert type(number) is int
|
||||
if number is None:
|
||||
raise ValueError("number")
|
||||
if 0 <= number < 16:
|
||||
return str(number)
|
||||
if 0 <= number < 0x100:
|
||||
return "${:02x}".format(number)
|
||||
if 0 <= number < 0x10000:
|
||||
return "${:04x}".format(number)
|
||||
raise OverflowError(number)
|
||||
|
||||
|
||||
def to_mflpt5(number: float) -> bytearray:
|
||||
# algorithm here https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a
|
||||
number = float(number)
|
||||
if number < FLOAT_MAX_NEGATIVE or number > FLOAT_MAX_POSITIVE:
|
||||
raise OverflowError("floating point number out of 5-byte mflpt range", number)
|
||||
if number == 0.0:
|
||||
return bytearray([0, 0, 0, 0, 0])
|
||||
if number < 0.0:
|
||||
sign = 0x80000000
|
||||
number = -number
|
||||
else:
|
||||
sign = 0x00000000
|
||||
mant, exp = math.frexp(number)
|
||||
exp += 128
|
||||
if exp < 1:
|
||||
# underflow, use zero instead
|
||||
return bytearray([0, 0, 0, 0, 0])
|
||||
if exp > 255:
|
||||
raise OverflowError("floating point number out of 5-byte mflpt range", number)
|
||||
mant = sign | int(mant * 0x100000000) & 0x7fffffff
|
||||
return bytearray([exp]) + int.to_bytes(mant, 4, "big")
|
||||
|
||||
|
||||
def mflpt5_to_float(mflpt: bytearray) -> float:
|
||||
# algorithm here https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a
|
||||
if mflpt == bytearray([0, 0, 0, 0, 0]):
|
||||
return 0.0
|
||||
exp = mflpt[0] - 128
|
||||
sign = mflpt[1] & 0x80
|
||||
number = 0x80000000 | int.from_bytes(mflpt[1:], "big")
|
||||
number = float(number) * 2**exp / 0x100000000
|
||||
return -number if sign else number
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def preserving_registers(registers: Set[str], scope: Scope, out: Callable, loads_a_within: bool=False, force_preserve: bool=False):
|
||||
# this sometimes clobbers a ZP scratch register and is therefore NOT safe to use in interrupts
|
@ -6,10 +6,11 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
"""
|
||||
|
||||
from typing import Callable
|
||||
from ..plyparse import Scope, Assignment, AugAssignment, Register, LiteralValue, SymbolName, VarDef, Dereference
|
||||
from . import CodeError, preserving_registers, to_hex, Context
|
||||
from ..datatypes import REGISTER_BYTES, VarType, DataType
|
||||
from ..compile import Zeropage
|
||||
from . import preserving_registers, Context
|
||||
from ..shared import CodeError, to_hex
|
||||
from ...plyparse import Scope, Assignment, AugAssignment, Register, LiteralValue, SymbolName, VarDef, Dereference
|
||||
from ...datatypes import REGISTER_BYTES, VarType, DataType
|
||||
from ...compile import Zeropage
|
||||
|
||||
|
||||
def generate_assignment(ctx: Context) -> None:
|
@ -5,8 +5,9 @@ This is the code generator for gotos and subroutine calls.
|
||||
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
"""
|
||||
|
||||
from ..plyparse import Goto, SubCall, LiteralValue, SymbolName, Dereference, Register
|
||||
from . import Context, CodeError, to_hex
|
||||
from . import Context
|
||||
from ..shared import CodeError, to_hex
|
||||
from ...plyparse import Goto, SubCall, LiteralValue, SymbolName, Dereference
|
||||
|
||||
|
||||
def generate_goto(ctx: Context) -> None:
|
@ -8,14 +8,15 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
import os
|
||||
import datetime
|
||||
from typing import TextIO, Callable, no_type_check
|
||||
from ..plylex import print_bold
|
||||
from ..plyparse import (Module, ProgramFormat, Block, Directive, VarDef, Label, Subroutine, ZpOptions,
|
||||
InlineAssembly, Return, Register, Goto, SubCall, Assignment, AugAssignment, IncrDecr)
|
||||
from . import CodeError, to_hex, to_mflpt5, Context
|
||||
from . import Context
|
||||
from .variables import generate_block_init, generate_block_vars
|
||||
from .assignment import generate_assignment, generate_aug_assignment
|
||||
from .calls import generate_goto, generate_subcall
|
||||
from .incrdecr import generate_incrdecr
|
||||
from ..shared import CodeError, to_hex, to_mflpt5
|
||||
from ...plylex import print_bold
|
||||
from ...plyparse import (Module, ProgramFormat, Block, Directive, VarDef, Label, Subroutine, ZpOptions,
|
||||
InlineAssembly, Return, Register, Goto, SubCall, Assignment, AugAssignment, IncrDecr)
|
||||
|
||||
|
||||
class Output:
|
@ -7,9 +7,10 @@ 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
|
||||
"""
|
||||
|
||||
from ..plyparse import VarDef, Register, IncrDecr, SymbolName, Dereference, LiteralValue, scoped_name
|
||||
from ..datatypes import VarType, DataType, REGISTER_BYTES
|
||||
from . import CodeError, preserving_registers, to_hex, Context
|
||||
from . import Context, preserving_registers
|
||||
from ..shared import CodeError, to_hex
|
||||
from ...plyparse import VarDef, Register, IncrDecr, SymbolName, Dereference, LiteralValue, scoped_name
|
||||
from ...datatypes import VarType, DataType, REGISTER_BYTES
|
||||
|
||||
|
||||
def generate_incrdecr(ctx: Context) -> None:
|
@ -7,9 +7,9 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
|
||||
from collections import defaultdict
|
||||
from typing import Dict, List, Callable, Any, no_type_check
|
||||
from ..plyparse import Block, VarDef, LiteralValue, AddressOf
|
||||
from ..datatypes import DataType, VarType, STRING_DATATYPES
|
||||
from . import to_hex, to_mflpt5, CodeError
|
||||
from ..shared import to_hex, to_mflpt5, CodeError
|
||||
from ...plyparse import Block, VarDef, LiteralValue, AddressOf
|
||||
from ...datatypes import DataType, VarType, STRING_DATATYPES
|
||||
|
||||
|
||||
def generate_block_init(out: Callable, block: Block) -> None:
|
64
il65/codegen/shared.py
Normal file
64
il65/codegen/shared.py
Normal file
@ -0,0 +1,64 @@
|
||||
"""
|
||||
Programming Language for 6502/6510 microprocessors, codename 'Sick'
|
||||
Shared logic for the code generators.
|
||||
|
||||
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
"""
|
||||
|
||||
|
||||
import math
|
||||
from ..datatypes import FLOAT_MAX_POSITIVE, FLOAT_MAX_NEGATIVE
|
||||
|
||||
|
||||
class CodeError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def to_hex(number: int) -> str:
|
||||
# 0..15 -> "0".."15"
|
||||
# 16..255 -> "$10".."$ff"
|
||||
# 256..65536 -> "$0100".."$ffff"
|
||||
assert type(number) is int
|
||||
if number is None:
|
||||
raise ValueError("number")
|
||||
if 0 <= number < 16:
|
||||
return str(number)
|
||||
if 0 <= number < 0x100:
|
||||
return "${:02x}".format(number)
|
||||
if 0 <= number < 0x10000:
|
||||
return "${:04x}".format(number)
|
||||
raise OverflowError(number)
|
||||
|
||||
|
||||
def to_mflpt5(number: float) -> bytearray:
|
||||
# algorithm here https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a
|
||||
number = float(number)
|
||||
if number < FLOAT_MAX_NEGATIVE or number > FLOAT_MAX_POSITIVE:
|
||||
raise OverflowError("floating point number out of 5-byte mflpt range", number)
|
||||
if number == 0.0:
|
||||
return bytearray([0, 0, 0, 0, 0])
|
||||
if number < 0.0:
|
||||
sign = 0x80000000
|
||||
number = -number
|
||||
else:
|
||||
sign = 0x00000000
|
||||
mant, exp = math.frexp(number)
|
||||
exp += 128
|
||||
if exp < 1:
|
||||
# underflow, use zero instead
|
||||
return bytearray([0, 0, 0, 0, 0])
|
||||
if exp > 255:
|
||||
raise OverflowError("floating point number out of 5-byte mflpt range", number)
|
||||
mant = sign | int(mant * 0x100000000) & 0x7fffffff
|
||||
return bytearray([exp]) + int.to_bytes(mant, 4, "big")
|
||||
|
||||
|
||||
def mflpt5_to_float(mflpt: bytearray) -> float:
|
||||
# algorithm here https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a
|
||||
if mflpt == bytearray([0, 0, 0, 0, 0]):
|
||||
return 0.0
|
||||
exp = mflpt[0] - 128
|
||||
sign = mflpt[1] & 0x80
|
||||
number = 0x80000000 | int.from_bytes(mflpt[1:], "big")
|
||||
number = float(number) * 2**exp / 0x100000000
|
||||
return -number if sign else number
|
8
il65/codegen/tinyvm/__init__.py
Normal file
8
il65/codegen/tinyvm/__init__.py
Normal file
@ -0,0 +1,8 @@
|
||||
"""
|
||||
Programming Language for 6502/6510 microprocessors, codename 'Sick'
|
||||
This is the tinyvm stack based program generator
|
||||
|
||||
Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
"""
|
||||
|
||||
# @todo
|
@ -12,7 +12,7 @@ import argparse
|
||||
import subprocess
|
||||
from .compile import PlyParser
|
||||
from .optimize import optimize
|
||||
from .emit.generate import AssemblyGenerator
|
||||
from .codegen.mos6502.generate import AssemblyGenerator
|
||||
from .plylex import print_bold
|
||||
from .plyparse import ProgramFormat
|
||||
|
||||
|
@ -18,12 +18,13 @@ from .datatypes import (DataType, VarType, REGISTER_SYMBOLS, REGISTER_BYTES, REG
|
||||
FLOAT_MAX_NEGATIVE, FLOAT_MAX_POSITIVE, char_to_bytevalue)
|
||||
|
||||
|
||||
__all__ = ["ProgramFormat", "ZpOptions", "math_functions", "builtin_functions", "ParseError", "ExpressionEvaluationError",
|
||||
"UndefinedSymbolError", "AstNode", "Directive", "Scope", "Block", "Module", "Label", "Expression",
|
||||
__all__ = ["ProgramFormat", "ZpOptions", "math_functions", "builtin_functions",
|
||||
"AstNode", "Directive", "Scope", "Block", "Module", "Label", "Expression",
|
||||
"Register", "Subroutine", "LiteralValue", "AddressOf", "SymbolName", "Dereference", "IncrDecr",
|
||||
"ExpressionWithOperator", "Goto", "SubCall", "VarDef", "Return", "Assignment", "AugAssignment",
|
||||
"InlineAssembly", "BuiltinFunction", "TokenFilter", "parser", "connect_parents", "DatatypeNode",
|
||||
"parse_file", "coerce_constant_value", "datatype_of", "check_symbol_definition", "NotCompiletimeConstantError"]
|
||||
"parse_file", "coerce_constant_value", "datatype_of", "check_symbol_definition", "scoped_name",
|
||||
"NotCompiletimeConstantError", "ExpressionEvaluationError", "ParseError", "UndefinedSymbolError"]
|
||||
|
||||
|
||||
class ProgramFormat(enum.Enum):
|
||||
|
@ -0,0 +1 @@
|
||||
# package
|
60
tests/test_codegen_mos6502.py
Normal file
60
tests/test_codegen_mos6502.py
Normal file
@ -0,0 +1,60 @@
|
||||
import pytest
|
||||
from il65.datatypes import FLOAT_MAX_NEGATIVE, FLOAT_MAX_POSITIVE
|
||||
from il65.codegen.shared import to_hex, to_mflpt5
|
||||
|
||||
|
||||
def test_to_hex():
|
||||
assert to_hex(0) == "0"
|
||||
assert to_hex(1) == "1"
|
||||
assert to_hex(10) == "10"
|
||||
assert to_hex(15) == "15"
|
||||
assert to_hex(16) == "$10"
|
||||
assert to_hex(255) == "$ff"
|
||||
assert to_hex(256) == "$0100"
|
||||
assert to_hex(20060) == "$4e5c"
|
||||
assert to_hex(65535) == "$ffff"
|
||||
with pytest.raises(OverflowError):
|
||||
to_hex(-1)
|
||||
with pytest.raises(OverflowError):
|
||||
to_hex(65536)
|
||||
|
||||
|
||||
def test_float_to_mflpt5():
|
||||
mflpt = to_mflpt5(1.0)
|
||||
assert type(mflpt) is bytearray
|
||||
assert b"\x00\x00\x00\x00\x00" == to_mflpt5(0)
|
||||
assert b"\x82\x49\x0F\xDA\xA1" == to_mflpt5(3.141592653)
|
||||
assert b"\x82\x49\x0F\xDA\xA2" == to_mflpt5(3.141592653589793)
|
||||
assert b"\x90\x80\x00\x00\x00" == to_mflpt5(-32768)
|
||||
assert b"\x81\x00\x00\x00\x00" == to_mflpt5(1)
|
||||
assert b"\x80\x35\x04\xF3\x34" == to_mflpt5(0.7071067812)
|
||||
assert b"\x80\x35\x04\xF3\x33" == to_mflpt5(0.7071067811865476)
|
||||
assert b"\x81\x35\x04\xF3\x34" == to_mflpt5(1.4142135624)
|
||||
assert b"\x81\x35\x04\xF3\x33" == to_mflpt5(1.4142135623730951)
|
||||
assert b"\x80\x80\x00\x00\x00" == to_mflpt5(-.5)
|
||||
assert b"\x80\x31\x72\x17\xF8" == to_mflpt5(0.69314718061)
|
||||
assert b"\x80\x31\x72\x17\xF7" == to_mflpt5(0.6931471805599453)
|
||||
assert b"\x84\x20\x00\x00\x00" == to_mflpt5(10)
|
||||
assert b"\x9E\x6E\x6B\x28\x00" == to_mflpt5(1000000000)
|
||||
assert b"\x80\x00\x00\x00\x00" == to_mflpt5(.5)
|
||||
assert b"\x81\x38\xAA\x3B\x29" == to_mflpt5(1.4426950408889634)
|
||||
assert b"\x81\x49\x0F\xDA\xA2" == to_mflpt5(1.5707963267948966)
|
||||
assert b"\x83\x49\x0F\xDA\xA2" == to_mflpt5(6.283185307179586)
|
||||
assert b"\x7F\x00\x00\x00\x00" == to_mflpt5(.25)
|
||||
|
||||
|
||||
def test_float_range():
|
||||
assert b"\xff\x7f\xff\xff\xff" == to_mflpt5(FLOAT_MAX_POSITIVE)
|
||||
assert b"\xff\xff\xff\xff\xff" == to_mflpt5(FLOAT_MAX_NEGATIVE)
|
||||
with pytest.raises(OverflowError):
|
||||
to_mflpt5(1.7014118346e+38)
|
||||
with pytest.raises(OverflowError):
|
||||
to_mflpt5(-1.7014118346e+38)
|
||||
with pytest.raises(OverflowError):
|
||||
to_mflpt5(1.7014118347e+38)
|
||||
with pytest.raises(OverflowError):
|
||||
to_mflpt5(-1.7014118347e+38)
|
||||
assert b"\x03\x39\x1d\x15\x63" == to_mflpt5(1.7e-38)
|
||||
assert b"\x00\x00\x00\x00\x00" == to_mflpt5(1.7e-39)
|
||||
assert b"\x03\xb9\x1d\x15\x63" == to_mflpt5(-1.7e-38)
|
||||
assert b"\x00\x00\x00\x00\x00" == to_mflpt5(-1.7e-39)
|
@ -1,9 +1,8 @@
|
||||
import pytest
|
||||
from il65.datatypes import DataType, STRING_DATATYPES, FLOAT_MAX_POSITIVE, FLOAT_MAX_NEGATIVE, char_to_bytevalue
|
||||
from il65.datatypes import DataType, STRING_DATATYPES, char_to_bytevalue
|
||||
from il65.plyparse import coerce_constant_value, LiteralValue, Scope, SymbolName, VarDef
|
||||
from il65.compile import ParseError
|
||||
from il65.plylex import SourceRef
|
||||
from il65.emit import to_hex, to_mflpt5
|
||||
|
||||
|
||||
def test_datatypes():
|
||||
@ -31,63 +30,6 @@ def test_parseerror():
|
||||
assert str(p) == "filename:99:42 message"
|
||||
|
||||
|
||||
def test_to_hex():
|
||||
assert to_hex(0) == "0"
|
||||
assert to_hex(1) == "1"
|
||||
assert to_hex(10) == "10"
|
||||
assert to_hex(15) == "15"
|
||||
assert to_hex(16) == "$10"
|
||||
assert to_hex(255) == "$ff"
|
||||
assert to_hex(256) == "$0100"
|
||||
assert to_hex(20060) == "$4e5c"
|
||||
assert to_hex(65535) == "$ffff"
|
||||
with pytest.raises(OverflowError):
|
||||
to_hex(-1)
|
||||
with pytest.raises(OverflowError):
|
||||
to_hex(65536)
|
||||
|
||||
|
||||
def test_float_to_mflpt5():
|
||||
mflpt = to_mflpt5(1.0)
|
||||
assert type(mflpt) is bytearray
|
||||
assert b"\x00\x00\x00\x00\x00" == to_mflpt5(0)
|
||||
assert b"\x82\x49\x0F\xDA\xA1" == to_mflpt5(3.141592653)
|
||||
assert b"\x82\x49\x0F\xDA\xA2" == to_mflpt5(3.141592653589793)
|
||||
assert b"\x90\x80\x00\x00\x00" == to_mflpt5(-32768)
|
||||
assert b"\x81\x00\x00\x00\x00" == to_mflpt5(1)
|
||||
assert b"\x80\x35\x04\xF3\x34" == to_mflpt5(0.7071067812)
|
||||
assert b"\x80\x35\x04\xF3\x33" == to_mflpt5(0.7071067811865476)
|
||||
assert b"\x81\x35\x04\xF3\x34" == to_mflpt5(1.4142135624)
|
||||
assert b"\x81\x35\x04\xF3\x33" == to_mflpt5(1.4142135623730951)
|
||||
assert b"\x80\x80\x00\x00\x00" == to_mflpt5(-.5)
|
||||
assert b"\x80\x31\x72\x17\xF8" == to_mflpt5(0.69314718061)
|
||||
assert b"\x80\x31\x72\x17\xF7" == to_mflpt5(0.6931471805599453)
|
||||
assert b"\x84\x20\x00\x00\x00" == to_mflpt5(10)
|
||||
assert b"\x9E\x6E\x6B\x28\x00" == to_mflpt5(1000000000)
|
||||
assert b"\x80\x00\x00\x00\x00" == to_mflpt5(.5)
|
||||
assert b"\x81\x38\xAA\x3B\x29" == to_mflpt5(1.4426950408889634)
|
||||
assert b"\x81\x49\x0F\xDA\xA2" == to_mflpt5(1.5707963267948966)
|
||||
assert b"\x83\x49\x0F\xDA\xA2" == to_mflpt5(6.283185307179586)
|
||||
assert b"\x7F\x00\x00\x00\x00" == to_mflpt5(.25)
|
||||
|
||||
|
||||
def test_float_range():
|
||||
assert b"\xff\x7f\xff\xff\xff" == to_mflpt5(FLOAT_MAX_POSITIVE)
|
||||
assert b"\xff\xff\xff\xff\xff" == to_mflpt5(FLOAT_MAX_NEGATIVE)
|
||||
with pytest.raises(OverflowError):
|
||||
to_mflpt5(1.7014118346e+38)
|
||||
with pytest.raises(OverflowError):
|
||||
to_mflpt5(-1.7014118346e+38)
|
||||
with pytest.raises(OverflowError):
|
||||
to_mflpt5(1.7014118347e+38)
|
||||
with pytest.raises(OverflowError):
|
||||
to_mflpt5(-1.7014118347e+38)
|
||||
assert b"\x03\x39\x1d\x15\x63" == to_mflpt5(1.7e-38)
|
||||
assert b"\x00\x00\x00\x00\x00" == to_mflpt5(1.7e-39)
|
||||
assert b"\x03\xb9\x1d\x15\x63" == to_mflpt5(-1.7e-38)
|
||||
assert b"\x00\x00\x00\x00\x00" == to_mflpt5(-1.7e-39)
|
||||
|
||||
|
||||
def test_char_to_bytevalue():
|
||||
assert char_to_bytevalue('a') == 65
|
||||
assert char_to_bytevalue('\n') == 13
|
||||
|
@ -8,7 +8,7 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
import enum
|
||||
import struct
|
||||
from typing import Callable
|
||||
from il65.emit import mflpt5_to_float, to_mflpt5
|
||||
from il65.codegen.shared import mflpt5_to_float, to_mflpt5
|
||||
|
||||
|
||||
class DataType(enum.IntEnum):
|
||||
|
18
tinyvm/vm.py
18
tinyvm/vm.py
@ -23,14 +23,12 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
# or in one of the dynamic variables.
|
||||
#
|
||||
# I/O: either via programmed I/O routines:
|
||||
# write [byte/bytearray to text output/screen],
|
||||
# read [byte/bytearray from keyboard],
|
||||
# wait [till any input comes available], @todo
|
||||
# check [if input is available) @todo
|
||||
# write [byte/bytearray to text output/screen] : syscall_printstr / syscall_printchr,
|
||||
# read [byte/bytearray from keyboard] : syscall_input / syscall_getchr (both blocking)
|
||||
# or via memory-mapped I/O (text screen matrix, keyboard scan register)
|
||||
#
|
||||
# CPU: stack based execution, no registers.
|
||||
# unlimited dynamic variables (v0, v1, ...) that have a value and a type.
|
||||
# CPU: single threaded, stack based execution,
|
||||
# no registers, but unlimited dynamic variables (v0, v1, ...) that have a value and a type.
|
||||
# types:
|
||||
# 1-bit boolean,
|
||||
# 8-bit byte (singed and unsigned),
|
||||
@ -41,9 +39,6 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
# matrix (2-dimensional array) of bytes (signed and unsigned).
|
||||
# all of these can have the flag CONST as well which means they cannot be modified.
|
||||
#
|
||||
# push (constant,
|
||||
# mark, unwind to previous mark.
|
||||
#
|
||||
# CPU INSTRUCTIONS:
|
||||
# stack manipulation mainly:
|
||||
# nop
|
||||
@ -53,12 +48,11 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
# jump label
|
||||
# jump_if_true label, jump_if_false label
|
||||
# jump_if_status_XX label special system dependent status register conditional check such as carry bit or overflow bit)
|
||||
# call function (arguments are on stack)
|
||||
# return (return values on stack)
|
||||
# syscall function (special system dependent implementation)
|
||||
# call function (arguments are on stack)
|
||||
# enter / exit (function call frame)
|
||||
#
|
||||
# TIMER INTERRUPT: triggered around each 1/60th of a second.
|
||||
# TIMER 'INTERRUPT': triggered around each 1/60th of a second.
|
||||
# executes on a DIFFERENT stack and with a different PROGRAM LIST,
|
||||
# but with access to ALL THE SAME DYNAMIC VARIABLES.
|
||||
# This suspends the main program until the timer program RETURNs!
|
||||
|
Loading…
Reference in New Issue
Block a user