added exit(rc) builtin function to immediately exit the program with a return code in A register

This commit is contained in:
Irmen de Jong 2020-03-13 02:05:15 +01:00
parent 796d07a7f8
commit 85c7f8314b
8 changed files with 135 additions and 92 deletions

View File

@ -651,6 +651,18 @@ greatereq_w .proc
bmi equal_b._equal_b_false bmi equal_b._equal_b_false
.pend .pend
orig_stackpointer .byte 0 ; stores the Stack pointer register at program start
func_exit .proc
; -- immediately exit the program with a return code in the A register
lda c64.ESTACK_LO+1,x
ldx orig_stackpointer
txs
rts ; return to original caller
.pend
func_read_flags .proc func_read_flags .proc
; -- put the processor status register on the stack ; -- put the processor status register on the stack
php php

View File

@ -9,7 +9,7 @@ import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.CompilerException import prog8.compiler.CompilerException
import prog8.functions.BuiltinFunctions import prog8.functions.BuiltinFunctions
import prog8.functions.FunctionSignature import prog8.functions.FSignature
internal class VarInitValueAndAddressOfCreator(private val program: Program): IAstModifyingVisitor { internal class VarInitValueAndAddressOfCreator(private val program: Program): IAstModifyingVisitor {
@ -129,7 +129,7 @@ internal class VarInitValueAndAddressOfCreator(private val program: Program): IA
} }
} }
private fun addAddressOfExprIfNeededForBuiltinFuncs(signature: FunctionSignature, args: MutableList<Expression>, parent: Statement) { private fun addAddressOfExprIfNeededForBuiltinFuncs(signature: FSignature, args: MutableList<Expression>, parent: Statement) {
// val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD // val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD
for(arg in args.withIndex().zip(signature.parameters)) { for(arg in args.withIndex().zip(signature.parameters)) {
val argvalue = arg.first.value val argvalue = arg.first.value

View File

@ -16,7 +16,7 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_HEX
import prog8.compiler.target.c64.Petscii import prog8.compiler.target.c64.Petscii
import prog8.compiler.target.generatedLabelPrefix import prog8.compiler.target.generatedLabelPrefix
import prog8.functions.BuiltinFunctions import prog8.functions.BuiltinFunctions
import prog8.functions.FunctionSignature import prog8.functions.FSignature
import java.math.RoundingMode import java.math.RoundingMode
import java.nio.file.Path import java.nio.file.Path
import java.time.LocalDate import java.time.LocalDate
@ -97,11 +97,15 @@ internal class AsmGen(private val program: Program,
out(" .null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8 by idj'") out(" .null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8 by idj'")
out("+\t.word 0") out("+\t.word 0")
out("_prog8_entrypoint\t; assembly code starts here\n") out("_prog8_entrypoint\t; assembly code starts here\n")
out(" tsx")
out(" stx prog8_lib.orig_stackpointer")
out(" jsr prog8_lib.init_system") out(" jsr prog8_lib.init_system")
} }
options.output == OutputType.PRG -> { options.output == OutputType.PRG -> {
out("; ---- program without basic sys call ----") out("; ---- program without basic sys call ----")
out("* = ${program.actualLoadAddress.toHex()}\n") out("* = ${program.actualLoadAddress.toHex()}\n")
out(" tsx")
out(" stx prog8_lib.orig_stackpointer")
out(" jsr prog8_lib.init_system") out(" jsr prog8_lib.init_system")
} }
options.output == OutputType.RAW -> { options.output == OutputType.RAW -> {
@ -138,7 +142,6 @@ internal class AsmGen(private val program: Program,
out(" jmp (c64.RESET_VEC)\t; cold reset") out(" jmp (c64.RESET_VEC)\t; cold reset")
} }
} }
out("")
} }
private fun footer() { private fun footer() {
@ -840,7 +843,7 @@ internal class AsmGen(private val program: Program,
internal fun translateExpression(expression: Expression) = internal fun translateExpression(expression: Expression) =
expressionsAsmGen.translateExpression(expression) expressionsAsmGen.translateExpression(expression)
internal fun translateFunctioncallExpression(functionCall: FunctionCall, signature: FunctionSignature) = internal fun translateFunctioncallExpression(functionCall: FunctionCall, signature: FSignature) =
builtinFunctionsAsmGen.translateFunctioncallExpression(functionCall, signature) builtinFunctionsAsmGen.translateFunctioncallExpression(functionCall, signature)
internal fun translateFunctionCall(functionCall: FunctionCall) = internal fun translateFunctionCall(functionCall: FunctionCall) =

View File

@ -16,19 +16,19 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_HEX
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_PLUS1_HEX import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_PLUS1_HEX
import prog8.compiler.toHex import prog8.compiler.toHex
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
import prog8.functions.FunctionSignature import prog8.functions.FSignature
internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen) {
internal fun translateFunctioncallExpression(fcall: FunctionCall, func: FunctionSignature) { internal fun translateFunctioncallExpression(fcall: FunctionCall, func: FSignature) {
translateFunctioncall(fcall, func, false) translateFunctioncall(fcall, func, false)
} }
internal fun translateFunctioncallStatement(fcall: FunctionCallStatement, func: FunctionSignature) { internal fun translateFunctioncallStatement(fcall: FunctionCallStatement, func: FSignature) {
translateFunctioncall(fcall, func, true) translateFunctioncall(fcall, func, true)
} }
private fun translateFunctioncall(fcall: IFunctionCall, func: FunctionSignature, discardResult: Boolean) { private fun translateFunctioncall(fcall: IFunctionCall, func: FSignature, discardResult: Boolean) {
val functionName = fcall.target.nameInSource.last() val functionName = fcall.target.nameInSource.last()
if (discardResult) { if (discardResult) {
if (func.pure) if (func.pure)
@ -603,7 +603,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
""") """)
} }
private fun translateFunctionArguments(args: MutableList<Expression>, signature: FunctionSignature) { private fun translateFunctionArguments(args: MutableList<Expression>, signature: FSignature) {
args.forEach { args.forEach {
asmgen.translateExpression(it) asmgen.translateExpression(it)
} }

View File

@ -7,88 +7,87 @@ import prog8.compiler.CompilerException
import kotlin.math.* import kotlin.math.*
class BuiltinFunctionParam(val name: String, val possibleDatatypes: Set<DataType>) class FParam(val name: String, val possibleDatatypes: Set<DataType>)
typealias ConstExpressionCaller = (args: List<Expression>, position: Position, program: Program) -> NumericLiteralValue typealias ConstExpressionCaller = (args: List<Expression>, position: Position, program: Program) -> NumericLiteralValue
class FunctionSignature(val pure: Boolean, // does it have side effects? class FSignature(val pure: Boolean, // does it have side effects?
val parameters: List<BuiltinFunctionParam>, val parameters: List<FParam>,
val returntype: DataType?, val returntype: DataType?,
val constExpressionFunc: ConstExpressionCaller? = null) val constExpressionFunc: ConstExpressionCaller? = null)
val BuiltinFunctions = mapOf( val BuiltinFunctions = mapOf(
// this set of function have no return value and operate in-place: // this set of function have no return value and operate in-place:
"rol" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "rol" to FSignature(false, listOf(FParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "ror" to FSignature(false, listOf(FParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "rol2" to FSignature(false, listOf(FParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "ror2" to FSignature(false, listOf(FParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", IntegerDatatypes)), null), "lsl" to FSignature(false, listOf(FParam("item", IntegerDatatypes)), null),
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", IntegerDatatypes)), null), "lsr" to FSignature(false, listOf(FParam("item", IntegerDatatypes)), null),
"sort" to FunctionSignature(false, listOf(BuiltinFunctionParam("array", ArrayDatatypes)), null), "sort" to FSignature(false, listOf(FParam("array", ArrayDatatypes)), null),
"reverse" to FunctionSignature(false, listOf(BuiltinFunctionParam("array", ArrayDatatypes)), null), "reverse" to FSignature(false, listOf(FParam("array", ArrayDatatypes)), null),
// these few have a return value depending on the argument(s): // these few have a return value depending on the argument(s):
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinMax) }, // type depends on args "max" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinMax) }, // type depends on args
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinMin) }, // type depends on args "min" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinMin) }, // type depends on args
"sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinSum) }, // type depends on args "sum" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinSum) }, // type depends on args
"abs" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", NumericDatatypes)), null, ::builtinAbs), // type depends on argument "abs" to FSignature(true, listOf(FParam("value", NumericDatatypes)), null, ::builtinAbs), // type depends on argument
"len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", IterableDatatypes)), null, ::builtinLen), // type is UBYTE or UWORD depending on actual length "len" to FSignature(true, listOf(FParam("values", IterableDatatypes)), null, ::builtinLen), // type is UBYTE or UWORD depending on actual length
// normal functions follow: // normal functions follow:
"sgn" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", NumericDatatypes)), DataType.BYTE, ::builtinSgn ), "sgn" to FSignature(true, listOf(FParam("value", NumericDatatypes)), DataType.BYTE, ::builtinSgn ),
"sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::sin) }, "sin" to FSignature(true, listOf(FParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::sin) },
"sin8" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.BYTE, ::builtinSin8 ), "sin8" to FSignature(true, listOf(FParam("angle8", setOf(DataType.UBYTE))), DataType.BYTE, ::builtinSin8 ),
"sin8u" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.UBYTE, ::builtinSin8u ), "sin8u" to FSignature(true, listOf(FParam("angle8", setOf(DataType.UBYTE))), DataType.UBYTE, ::builtinSin8u ),
"sin16" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.WORD, ::builtinSin16 ), "sin16" to FSignature(true, listOf(FParam("angle8", setOf(DataType.UBYTE))), DataType.WORD, ::builtinSin16 ),
"sin16u" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.UWORD, ::builtinSin16u ), "sin16u" to FSignature(true, listOf(FParam("angle8", setOf(DataType.UBYTE))), DataType.UWORD, ::builtinSin16u ),
"cos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::cos) }, "cos" to FSignature(true, listOf(FParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::cos) },
"cos8" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.BYTE, ::builtinCos8 ), "cos8" to FSignature(true, listOf(FParam("angle8", setOf(DataType.UBYTE))), DataType.BYTE, ::builtinCos8 ),
"cos8u" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.UBYTE, ::builtinCos8u ), "cos8u" to FSignature(true, listOf(FParam("angle8", setOf(DataType.UBYTE))), DataType.UBYTE, ::builtinCos8u ),
"cos16" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.WORD, ::builtinCos16 ), "cos16" to FSignature(true, listOf(FParam("angle8", setOf(DataType.UBYTE))), DataType.WORD, ::builtinCos16 ),
"cos16u" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.UWORD, ::builtinCos16u ), "cos16u" to FSignature(true, listOf(FParam("angle8", setOf(DataType.UBYTE))), DataType.UWORD, ::builtinCos16u ),
"tan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::tan) }, "tan" to FSignature(true, listOf(FParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::tan) },
"atan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::atan) }, "atan" to FSignature(true, listOf(FParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::atan) },
"ln" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::log) }, "ln" to FSignature(true, listOf(FParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::log) },
"log2" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, ::log2) }, "log2" to FSignature(true, listOf(FParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, ::log2) },
"sqrt16" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UWORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { sqrt(it.toDouble()).toInt() } }, "sqrt16" to FSignature(true, listOf(FParam("value", setOf(DataType.UWORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { sqrt(it.toDouble()).toInt() } },
"sqrt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::sqrt) }, "sqrt" to FSignature(true, listOf(FParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::sqrt) },
"rad" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::toRadians) }, "rad" to FSignature(true, listOf(FParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::toRadians) },
"deg" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::toDegrees) }, "deg" to FSignature(true, listOf(FParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::toDegrees) },
"round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, Math::round) }, "round" to FSignature(true, listOf(FParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, Math::round) },
"floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, Math::floor) }, "floor" to FSignature(true, listOf(FParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, Math::floor) },
"ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, Math::ceil) }, "ceil" to FSignature(true, listOf(FParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, Math::ceil) },
"any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, prg -> collectionArg(a, p, prg, ::builtinAny) }, "any" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, prg -> collectionArg(a, p, prg, ::builtinAny) },
"all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, prg -> collectionArg(a, p, prg, ::builtinAll) }, "all" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, prg -> collectionArg(a, p, prg, ::builtinAll) },
"lsb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> x and 255 }}, "lsb" to FSignature(true, listOf(FParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> x and 255 }},
"msb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> x ushr 8 and 255}}, "msb" to FSignature(true, listOf(FParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> x ushr 8 and 255}},
"mkword" to FunctionSignature(true, listOf( "mkword" to FSignature(true, listOf(FParam("lsb", setOf(DataType.UBYTE)), FParam("msb", setOf(DataType.UBYTE))), DataType.UWORD, ::builtinMkword),
BuiltinFunctionParam("lsb", setOf(DataType.UBYTE)), "rnd" to FSignature(true, emptyList(), DataType.UBYTE),
BuiltinFunctionParam("msb", setOf(DataType.UBYTE))), DataType.UWORD, ::builtinMkword), "rndw" to FSignature(true, emptyList(), DataType.UWORD),
"rnd" to FunctionSignature(true, emptyList(), DataType.UBYTE), "rndf" to FSignature(true, emptyList(), DataType.FLOAT),
"rndw" to FunctionSignature(true, emptyList(), DataType.UWORD), "exit" to FSignature(false, listOf(FParam("returnvalue", setOf(DataType.UBYTE))), null),
"rndf" to FunctionSignature(true, emptyList(), DataType.FLOAT), "rsave" to FSignature(false, emptyList(), null),
"rsave" to FunctionSignature(false, emptyList(), null), "rrestore" to FSignature(false, emptyList(), null),
"rrestore" to FunctionSignature(false, emptyList(), null), "set_carry" to FSignature(false, emptyList(), null),
"set_carry" to FunctionSignature(false, emptyList(), null), "clear_carry" to FSignature(false, emptyList(), null),
"clear_carry" to FunctionSignature(false, emptyList(), null), "set_irqd" to FSignature(false, emptyList(), null),
"set_irqd" to FunctionSignature(false, emptyList(), null), "clear_irqd" to FSignature(false, emptyList(), null),
"clear_irqd" to FunctionSignature(false, emptyList(), null), "read_flags" to FSignature(false, emptyList(), DataType.UBYTE),
"read_flags" to FunctionSignature(false, emptyList(), DataType.UBYTE), "swap" to FSignature(false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), null),
"swap" to FunctionSignature(false, listOf(BuiltinFunctionParam("first", NumericDatatypes), BuiltinFunctionParam("second", NumericDatatypes)), null), "memcopy" to FSignature(false, listOf(
"memcopy" to FunctionSignature(false, listOf( FParam("from", IterableDatatypes + DataType.UWORD),
BuiltinFunctionParam("from", IterableDatatypes + DataType.UWORD), FParam("to", IterableDatatypes + DataType.UWORD),
BuiltinFunctionParam("to", IterableDatatypes + DataType.UWORD), FParam("numbytes", setOf(DataType.UBYTE))), null),
BuiltinFunctionParam("numbytes", setOf(DataType.UBYTE))), null), "memset" to FSignature(false, listOf(
"memset" to FunctionSignature(false, listOf( FParam("address", IterableDatatypes + DataType.UWORD),
BuiltinFunctionParam("address", IterableDatatypes + DataType.UWORD), FParam("numbytes", setOf(DataType.UWORD)),
BuiltinFunctionParam("numbytes", setOf(DataType.UWORD)), FParam("bytevalue", ByteDatatypes)), null),
BuiltinFunctionParam("bytevalue", ByteDatatypes)), null), "memsetw" to FSignature(false, listOf(
"memsetw" to FunctionSignature(false, listOf( FParam("address", IterableDatatypes + DataType.UWORD),
BuiltinFunctionParam("address", IterableDatatypes + DataType.UWORD), FParam("numwords", setOf(DataType.UWORD)),
BuiltinFunctionParam("numwords", setOf(DataType.UWORD)), FParam("wordvalue", setOf(DataType.UWORD, DataType.WORD))), null),
BuiltinFunctionParam("wordvalue", setOf(DataType.UWORD, DataType.WORD))), null), "strlen" to FSignature(true, listOf(FParam("string", setOf(DataType.STR))), DataType.UBYTE, ::builtinStrlen)
"strlen" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", setOf(DataType.STR))), DataType.UBYTE, ::builtinStrlen)
) )
fun builtinMax(array: List<Number>): Number = array.maxBy { it.toDouble() }!! fun builtinMax(array: List<Number>): Number = array.maxBy { it.toDouble() }!!

View File

@ -836,6 +836,10 @@ rrestore()
read_flags() read_flags()
Returns the current value of the CPU status register. Returns the current value of the CPU status register.
exit(returncode)
Immediately stops the program and exits it, with the returncode in the A register.
Note: custom interrupt handlers remain active unless manually cleared first!
Library routines Library routines

View File

@ -3,7 +3,8 @@ TODO
==== ====
- option to load library files from a directory instead of the embedded ones - option to load library files from a directory instead of the embedded ones
- exit('message', returncode) function to immediately exit the program with this message (restores stack) - compiler warning 'unreachable code' for statement following an exit() function call
- code optimizer: remove all statements following an exit() function call
- vector inc/dec/add/sub/mul/div...? - vector inc/dec/add/sub/mul/div...?
arrayvar++ / arrayvar-- / arrayvar += 2 / arrayvar -= 2 / arrayvar *= 3 / arrayvar /= 3 arrayvar++ / arrayvar-- / arrayvar += 2 / arrayvar -= 2 / arrayvar *= 3 / arrayvar /= 3

View File

@ -4,14 +4,38 @@
main { main {
sub start() { sub start() {
c64scr.print("spstart:")
print_stackpointer()
sub1()
c64scr.print("spend:")
print_stackpointer()
}
lsr(@(9999+A)) sub sub1() {
ror(@(9999+A)) c64scr.print("sp1:")
rol(@(9999+A)) print_stackpointer()
ror2(@(9999+A)) sub2()
rol2(@(9999+A)) }
c64scr.print_ub(X) sub sub2() {
c64scr.print("sp2:")
print_stackpointer()
exit(65)
sub3() ; TODO unreachable code compiler warning + remove the code in optimizer
sub3() ; TODO unreachable code compiler warning + remove the code in optimizer
sub3() ; TODO unreachable code compiler warning + remove the code in optimizer
}
sub sub3() {
c64scr.print("sp3:")
print_stackpointer()
}
sub print_stackpointer() {
%asm {{
tsx
}}
c64scr.print_ub(X) ; prints stack pointer
c64.CHROUT('\n')
} }
} }