From c2eb181b5afb5a81f77c2327aed4014e76a4cf70 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 1 Jan 2019 18:38:43 +0100 Subject: [PATCH] added memcopy function --- compiler/examples/sprites.p8 | 13 +---------- compiler/examples/test.p8 | 4 ++++ compiler/src/prog8/ast/AST.kt | 8 ++++++- compiler/src/prog8/ast/AstChecker.kt | 7 ++++++ .../src/prog8/functions/BuiltinFunctions.kt | 4 ++++ compiler/src/prog8/stackvm/StackVm.kt | 4 +++- docs/source/programming.rst | 7 ++++++ prog8lib/prog8lib.p8 | 22 +++++++++++++++++++ 8 files changed, 55 insertions(+), 14 deletions(-) diff --git a/compiler/examples/sprites.p8 b/compiler/examples/sprites.p8 index 0fcbfa044..f0434f3c8 100644 --- a/compiler/examples/sprites.p8 +++ b/compiler/examples/sprites.p8 @@ -35,13 +35,7 @@ c64.STROUT("balloon sprites!\n") c64.STROUT("...we are all floating...\n") - ; copy the ballon sprite data to the correct address and setup the sprite pointers - ; @todo make a memcopy function for this, that calls c64utils.memcopy - for ubyte i in 0 to 63 { - ;@(sprite_data_address+i) = @(balloonsprite+i) ; @todo nice error message - @(sprite_data_address+i) = balloonsprite[i] - } - + memcopy(balloonsprite, sprite_data_address, 63) c64.SPRPTR0 = sprite_data_address//64 c64.SPRPTR1 = sprite_data_address//64 c64.SPRPTR2 = sprite_data_address//64 @@ -59,11 +53,6 @@ c64.SPENA = 255 ; enable all sprites set_irqvec() ; enable animation - ;set_irqvec_excl() ; enable animation - } - - sub foobar() { - A=99 } } diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 54d8643fc..7ae258080 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -1,6 +1,7 @@ %import c64utils ~ main { + ubyte[3] balloonsprite = [ %00000000,%01111111,%00000000 ] sub start() { ubyte i=0 @@ -13,5 +14,8 @@ @($d020) = @($d020+i) + 1 @($d020+i) = @($d020+i) + 1 c64scr.print_ub(X) + + i = 2+balloonsprite + } } diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 97c759efe..a0761f874 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -851,7 +851,13 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I val leftDt = left.resultingDatatype(namespace, heap) val rightDt = right.resultingDatatype(namespace, heap) return when(operator) { - "+", "-", "*", "**", "%" -> if(leftDt==null || rightDt==null) null else arithmeticOpDt(leftDt, rightDt) + "+", "-", "*", "**", "%" -> if(leftDt==null || rightDt==null) null else { + try { + arithmeticOpDt(leftDt, rightDt) + } catch(x: FatalAstException) { + null + } + } "//" -> if(leftDt==null || rightDt==null) null else integerDivisionOpDt(leftDt, rightDt) "&" -> leftDt "|" -> leftDt diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 52d6a9154..c8560060c 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -696,6 +696,13 @@ class AstChecker(private val namespace: INameScope, } } } + + val leftDt = expr.left.resultingDatatype(namespace, heap)!! + val rightDt = expr.right.resultingDatatype(namespace, heap)!! + if(leftDt !in NumericDatatypes) + checkResult.add(ExpressionError("left operand is not numeric", expr.left.position)) + if(rightDt!in NumericDatatypes) + checkResult.add(ExpressionError("right operand is not numeric", expr.right.position)) return super.process(expr) } diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 995ed33c9..753efcbc7 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -57,6 +57,10 @@ val BuiltinFunctions = mapOf( "set_irqvec" to FunctionSignature(false, emptyList(), null), "set_irqvec_excl" to FunctionSignature(false, emptyList(), null), "restore_irqvec" to FunctionSignature(false, emptyList(), null), + "memcopy" to FunctionSignature(false, listOf( + BuiltinFunctionParam("from", IntegerDatatypes + IterableDatatypes), + BuiltinFunctionParam("to", IntegerDatatypes + IterableDatatypes), + BuiltinFunctionParam("numbytes", IntegerDatatypes)), null), "vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null), "vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null), "vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), null), diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index c52630c22..85d2ce869 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -72,7 +72,8 @@ enum class Syscall(val callNr: Short) { FUNC_SUM_F(134), FUNC_SET_IRQVEC(135), FUNC_SET_IRQVEC_EXCL(136), - FUNC_RESTORE_IRQVEC(137) + FUNC_RESTORE_IRQVEC(137), + FUNC_MEMCOPY(138) // note: not all builtin functions of the Prog8 language are present as functions: // some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL_BYTE, ROR, ROL2, ROR2, and FLT)! @@ -1614,6 +1615,7 @@ class StackVm(private var traceOutputFile: String?) { } Syscall.FUNC_SET_IRQVEC, Syscall.FUNC_SET_IRQVEC_EXCL -> TODO() Syscall.FUNC_RESTORE_IRQVEC -> TODO() + Syscall.FUNC_MEMCOPY -> TODO() } } diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 56804916d..37347b7fe 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -618,6 +618,13 @@ ror2(x) It uses some extra logic to not consider the carry flag as extra rotation bit. Modifies in-place, doesn't return a value (so can't be used in an expression). +memcopy(from, to, numbytes) + Efficiently copy a number of bytes (1 - 256) from a memory location to another. + NOTE: 'to' must NOT overlap with 'from', unless it is *before* 'from'. + Because this function imposes some overhead to handle the parameters, + it is only faster if the number of bytes is larger than a certain threshold. + Compare the generated code to see if it was beneficial or not. + set_carry() / clear_carry() Set (or clear) the CPU status register Carry flag. No result value. (translated into ``SEC`` or ``CLC`` cpu instruction) diff --git a/prog8lib/prog8lib.p8 b/prog8lib/prog8lib.p8 index 4382b63b8..252812060 100644 --- a/prog8lib/prog8lib.p8 +++ b/prog8lib/prog8lib.p8 @@ -1589,6 +1589,28 @@ func_rndf .proc _rndf_rnum5 .byte 0,0,0,0,0 .pend + +func_memcopy .proc ; clobbers A,Y + inx + stx SCRATCH_ZPREGX + lda ESTACK_LO+2,x + sta SCRATCH_ZPWORD1 + lda ESTACK_HI+2,x + sta SCRATCH_ZPWORD1+1 + lda ESTACK_HI+1,x + tay + lda ESTACK_LO+1,x + pha + lda ESTACK_LO,x + tax + pla + jsr c64utils.memcopy + ldx SCRATCH_ZPREGX + inx + inx + rts + .pend + }} }