mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
argument type casts for builtin functions, added memset, tweaked memcopy/memset assembly a bit
This commit is contained in:
parent
dd02d97db4
commit
d37c9d1680
@ -292,134 +292,6 @@ asmsub str2word(str string @ AY) -> clobbers() -> (word @ AY) {
|
|||||||
|
|
||||||
; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html
|
; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html
|
||||||
|
|
||||||
%asm {{
|
|
||||||
; copy memory UP from (SCRATCH_ZPWORD1) to (SCRATCH_ZPWORD2) of length X/Y (16-bit, X=lo, Y=hi)
|
|
||||||
; clobbers register A,X,Y
|
|
||||||
memcopy16_up .proc
|
|
||||||
source = SCRATCH_ZPWORD1
|
|
||||||
dest = SCRATCH_ZPWORD2
|
|
||||||
length = SCRATCH_ZPB1 ; (and SCRATCH_ZPREG)
|
|
||||||
|
|
||||||
stx length
|
|
||||||
sty length+1
|
|
||||||
|
|
||||||
ldx length ; move low byte of length into X
|
|
||||||
bne + ; jump to start if X > 0
|
|
||||||
dec length ; subtract 1 from length
|
|
||||||
+ ldy #0 ; set Y to 0
|
|
||||||
- lda (source),y ; set A to whatever (source) points to offset by Y
|
|
||||||
sta (dest),y ; move A to location pointed to by (dest) offset by Y
|
|
||||||
iny ; increment Y
|
|
||||||
bne + ; if Y<>0 then (rolled over) then still moving bytes
|
|
||||||
inc source+1 ; increment hi byte of source
|
|
||||||
inc dest+1 ; increment hi byte of dest
|
|
||||||
+ dex ; decrement X (lo byte counter)
|
|
||||||
bne - ; if X<>0 then move another byte
|
|
||||||
dec length ; we've moved 255 bytes, dec length
|
|
||||||
bpl - ; if length is still positive go back and move more
|
|
||||||
rts ; done
|
|
||||||
.pend
|
|
||||||
|
|
||||||
|
|
||||||
; 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
|
|
||||||
|
|
||||||
memcopy .proc
|
|
||||||
sta c64.SCRATCH_ZPWORD2
|
|
||||||
sty c64.SCRATCH_ZPWORD2+1
|
|
||||||
ldy #0
|
|
||||||
- lda (c64.SCRATCH_ZPWORD1), y
|
|
||||||
sta (c64.SCRATCH_ZPWORD2), y
|
|
||||||
iny
|
|
||||||
dex
|
|
||||||
bne -
|
|
||||||
rts
|
|
||||||
.pend
|
|
||||||
|
|
||||||
|
|
||||||
; fill memory from (SCRATCH_ZPWORD1), length XY, with value in A.
|
|
||||||
; clobbers X, Y
|
|
||||||
memset .proc
|
|
||||||
stx SCRATCH_ZPB1
|
|
||||||
sty SCRATCH_ZPREG
|
|
||||||
ldy #0
|
|
||||||
ldx SCRATCH_ZPREG
|
|
||||||
beq _lastpage
|
|
||||||
|
|
||||||
_fullpage sta (SCRATCH_ZPWORD1),y
|
|
||||||
iny
|
|
||||||
bne _fullpage
|
|
||||||
inc SCRATCH_ZPWORD1+1 ; next page
|
|
||||||
dex
|
|
||||||
bne _fullpage
|
|
||||||
|
|
||||||
_lastpage ldy SCRATCH_ZPB1
|
|
||||||
beq +
|
|
||||||
- dey
|
|
||||||
sta (SCRATCH_ZPWORD1),y
|
|
||||||
bne -
|
|
||||||
|
|
||||||
+ rts
|
|
||||||
.pend
|
|
||||||
|
|
||||||
|
|
||||||
; fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
|
|
||||||
; clobbers A, X, Y
|
|
||||||
memsetw .proc
|
|
||||||
sta _mod1+1 ; self-modify
|
|
||||||
sty _mod1b+1 ; self-modify
|
|
||||||
sta _mod2+1 ; self-modify
|
|
||||||
sty _mod2b+1 ; self-modify
|
|
||||||
ldx SCRATCH_ZPWORD1
|
|
||||||
stx SCRATCH_ZPB1
|
|
||||||
ldx SCRATCH_ZPWORD1+1
|
|
||||||
inx
|
|
||||||
stx SCRATCH_ZPREG ; second page
|
|
||||||
|
|
||||||
ldy #0
|
|
||||||
ldx SCRATCH_ZPWORD2+1
|
|
||||||
beq _lastpage
|
|
||||||
|
|
||||||
_fullpage
|
|
||||||
_mod1 lda #0 ; self-modified
|
|
||||||
sta (SCRATCH_ZPWORD1),y ; first page
|
|
||||||
sta (SCRATCH_ZPB1),y ; second page
|
|
||||||
iny
|
|
||||||
_mod1b lda #0 ; self-modified
|
|
||||||
sta (SCRATCH_ZPWORD1),y ; first page
|
|
||||||
sta (SCRATCH_ZPB1),y ; second page
|
|
||||||
iny
|
|
||||||
bne _fullpage
|
|
||||||
inc SCRATCH_ZPWORD1+1 ; next page pair
|
|
||||||
inc SCRATCH_ZPWORD1+1 ; next page pair
|
|
||||||
inc SCRATCH_ZPB1+1 ; next page pair
|
|
||||||
inc SCRATCH_ZPB1+1 ; next page pair
|
|
||||||
dex
|
|
||||||
bne _fullpage
|
|
||||||
|
|
||||||
_lastpage ldx SCRATCH_ZPWORD2
|
|
||||||
beq _done
|
|
||||||
|
|
||||||
ldy #0
|
|
||||||
-
|
|
||||||
_mod2 lda #0 ; self-modified
|
|
||||||
sta (SCRATCH_ZPWORD1), y
|
|
||||||
inc SCRATCH_ZPWORD1
|
|
||||||
bne _mod2b
|
|
||||||
inc SCRATCH_ZPWORD1+1
|
|
||||||
_mod2b lda #0 ; self-modified
|
|
||||||
sta (SCRATCH_ZPWORD1), y
|
|
||||||
inc SCRATCH_ZPWORD1
|
|
||||||
bne +
|
|
||||||
inc SCRATCH_ZPWORD1+1
|
|
||||||
+ dex
|
|
||||||
bne -
|
|
||||||
_done rts
|
|
||||||
.pend
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
|
|
||||||
asmsub set_irqvec_excl() -> clobbers(A) -> () {
|
asmsub set_irqvec_excl() -> clobbers(A) -> () {
|
||||||
%asm {{
|
%asm {{
|
||||||
|
@ -1012,14 +1012,172 @@ func_memcopy .proc
|
|||||||
lda c64.ESTACK_HI+2,x
|
lda c64.ESTACK_HI+2,x
|
||||||
sta c64.SCRATCH_ZPWORD1+1
|
sta c64.SCRATCH_ZPWORD1+1
|
||||||
lda c64.ESTACK_LO+1,x
|
lda c64.ESTACK_LO+1,x
|
||||||
ldy c64.ESTACK_HI+1,x
|
sta c64.SCRATCH_ZPWORD2
|
||||||
pha
|
lda c64.ESTACK_HI+1,x
|
||||||
|
sta c64.SCRATCH_ZPWORD2+1
|
||||||
lda c64.ESTACK_LO,x
|
lda c64.ESTACK_LO,x
|
||||||
tax
|
tax
|
||||||
pla
|
ldy #0
|
||||||
jsr c64utils.memcopy
|
- lda (c64.SCRATCH_ZPWORD1), y
|
||||||
|
sta (c64.SCRATCH_ZPWORD2), y
|
||||||
|
iny
|
||||||
|
dex
|
||||||
|
bne -
|
||||||
ldx c64.SCRATCH_ZPREGX
|
ldx c64.SCRATCH_ZPREGX
|
||||||
inx
|
inx
|
||||||
inx
|
inx
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
func_memset .proc
|
||||||
|
; note: clobbers A,Y
|
||||||
|
inx
|
||||||
|
stx c64.SCRATCH_ZPREGX
|
||||||
|
lda c64.ESTACK_LO+2,x
|
||||||
|
sta c64.SCRATCH_ZPWORD1
|
||||||
|
lda c64.ESTACK_HI+2,x
|
||||||
|
sta c64.SCRATCH_ZPWORD1+1
|
||||||
|
lda c64.ESTACK_LO+1,x
|
||||||
|
sta c64.SCRATCH_ZPB1
|
||||||
|
ldy c64.ESTACK_HI+1,x
|
||||||
|
lda c64.ESTACK_LO,x
|
||||||
|
ldx c64.SCRATCH_ZPB1
|
||||||
|
jsr memset
|
||||||
|
ldx c64.SCRATCH_ZPREGX
|
||||||
|
inx
|
||||||
|
inx
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
func_memsetw .proc
|
||||||
|
; note: clobbers A,Y
|
||||||
|
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
|
||||||
|
|
||||||
|
inx
|
||||||
|
stx c64.SCRATCH_ZPREGX
|
||||||
|
lda c64.ESTACK_LO+2,x
|
||||||
|
sta c64.SCRATCH_ZPWORD1
|
||||||
|
lda c64.ESTACK_HI+2,x
|
||||||
|
sta c64.SCRATCH_ZPWORD1+1
|
||||||
|
lda c64.ESTACK_LO+1,x
|
||||||
|
sta c64.SCRATCH_ZPWORD2
|
||||||
|
lda c64.ESTACK_HI+1,x
|
||||||
|
sta c64.SCRATCH_ZPWORD2+1
|
||||||
|
lda c64.ESTACK_LO,x
|
||||||
|
ldy c64.ESTACK_HI,x
|
||||||
|
jsr memsetw
|
||||||
|
ldx c64.SCRATCH_ZPREGX
|
||||||
|
inx
|
||||||
|
inx
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
memcopy16_up .proc
|
||||||
|
; -- copy memory UP from (SCRATCH_ZPWORD1) to (SCRATCH_ZPWORD2) of length X/Y (16-bit, X=lo, Y=hi)
|
||||||
|
; clobbers register A,X,Y
|
||||||
|
source = c64.SCRATCH_ZPWORD1
|
||||||
|
dest = c64.SCRATCH_ZPWORD2
|
||||||
|
length = c64.SCRATCH_ZPB1 ; (and SCRATCH_ZPREG)
|
||||||
|
|
||||||
|
stx length
|
||||||
|
sty length+1
|
||||||
|
|
||||||
|
ldx length ; move low byte of length into X
|
||||||
|
bne + ; jump to start if X > 0
|
||||||
|
dec length ; subtract 1 from length
|
||||||
|
+ ldy #0 ; set Y to 0
|
||||||
|
- lda (source),y ; set A to whatever (source) points to offset by Y
|
||||||
|
sta (dest),y ; move A to location pointed to by (dest) offset by Y
|
||||||
|
iny ; increment Y
|
||||||
|
bne + ; if Y<>0 then (rolled over) then still moving bytes
|
||||||
|
inc source+1 ; increment hi byte of source
|
||||||
|
inc dest+1 ; increment hi byte of dest
|
||||||
|
+ dex ; decrement X (lo byte counter)
|
||||||
|
bne - ; if X<>0 then move another byte
|
||||||
|
dec length ; we've moved 255 bytes, dec length
|
||||||
|
bpl - ; if length is still positive go back and move more
|
||||||
|
rts ; done
|
||||||
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
memset .proc
|
||||||
|
; -- fill memory from (SCRATCH_ZPWORD1), length XY, with value in A.
|
||||||
|
; clobbers X, Y
|
||||||
|
stx c64.SCRATCH_ZPB1
|
||||||
|
sty c64.SCRATCH_ZPREG
|
||||||
|
ldy #0
|
||||||
|
ldx c64.SCRATCH_ZPREG
|
||||||
|
beq _lastpage
|
||||||
|
|
||||||
|
_fullpage sta (c64.SCRATCH_ZPWORD1),y
|
||||||
|
iny
|
||||||
|
bne _fullpage
|
||||||
|
inc c64.SCRATCH_ZPWORD1+1 ; next page
|
||||||
|
dex
|
||||||
|
bne _fullpage
|
||||||
|
|
||||||
|
_lastpage ldy c64.SCRATCH_ZPB1
|
||||||
|
beq +
|
||||||
|
- dey
|
||||||
|
sta (c64.SCRATCH_ZPWORD1),y
|
||||||
|
bne -
|
||||||
|
|
||||||
|
+ rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
memsetw .proc
|
||||||
|
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
|
||||||
|
; clobbers A, X, Y
|
||||||
|
sta _mod1+1 ; self-modify
|
||||||
|
sty _mod1b+1 ; self-modify
|
||||||
|
sta _mod2+1 ; self-modify
|
||||||
|
sty _mod2b+1 ; self-modify
|
||||||
|
ldx c64.SCRATCH_ZPWORD1
|
||||||
|
stx c64.SCRATCH_ZPB1
|
||||||
|
ldx c64.SCRATCH_ZPWORD1+1
|
||||||
|
inx
|
||||||
|
stx c64.SCRATCH_ZPREG ; second page
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
ldx c64.SCRATCH_ZPWORD2+1
|
||||||
|
beq _lastpage
|
||||||
|
|
||||||
|
_fullpage
|
||||||
|
_mod1 lda #0 ; self-modified
|
||||||
|
sta (c64.SCRATCH_ZPWORD1),y ; first page
|
||||||
|
sta (c64.SCRATCH_ZPB1),y ; second page
|
||||||
|
iny
|
||||||
|
_mod1b lda #0 ; self-modified
|
||||||
|
sta (c64.SCRATCH_ZPWORD1),y ; first page
|
||||||
|
sta (c64.SCRATCH_ZPB1),y ; second page
|
||||||
|
iny
|
||||||
|
bne _fullpage
|
||||||
|
inc c64.SCRATCH_ZPWORD1+1 ; next page pair
|
||||||
|
inc c64.SCRATCH_ZPWORD1+1 ; next page pair
|
||||||
|
inc c64.SCRATCH_ZPB1+1 ; next page pair
|
||||||
|
inc c64.SCRATCH_ZPB1+1 ; next page pair
|
||||||
|
dex
|
||||||
|
bne _fullpage
|
||||||
|
|
||||||
|
_lastpage ldx c64.SCRATCH_ZPWORD2
|
||||||
|
beq _done
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
-
|
||||||
|
_mod2 lda #0 ; self-modified
|
||||||
|
sta (c64.SCRATCH_ZPWORD1), y
|
||||||
|
inc c64.SCRATCH_ZPWORD1
|
||||||
|
bne _mod2b
|
||||||
|
inc c64.SCRATCH_ZPWORD1+1
|
||||||
|
_mod2b lda #0 ; self-modified
|
||||||
|
sta (c64.SCRATCH_ZPWORD1), y
|
||||||
|
inc c64.SCRATCH_ZPWORD1
|
||||||
|
bne +
|
||||||
|
inc c64.SCRATCH_ZPWORD1+1
|
||||||
|
+ dex
|
||||||
|
bne -
|
||||||
|
_done rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
@ -51,6 +51,10 @@ enum class DataType {
|
|||||||
ARRAY_W -> targetType == UWORD
|
ARRAY_W -> targetType == UWORD
|
||||||
ARRAY_F -> targetType == UWORD
|
ARRAY_F -> targetType == UWORD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun assignableTo(targetTypes: Set<DataType>) = targetTypes.any { this.assignableTo(it) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Register {
|
enum class Register {
|
||||||
|
@ -784,10 +784,11 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
else {
|
else {
|
||||||
for (arg in args.withIndex().zip(func.parameters)) {
|
for (arg in args.withIndex().zip(func.parameters)) {
|
||||||
val argDt=arg.first.value.resultingDatatype(namespace, heap)
|
val argDt=arg.first.value.resultingDatatype(namespace, heap)
|
||||||
if(argDt !in arg.second.possibleDatatypes)
|
if(argDt!=null && !argDt.assignableTo(arg.second.possibleDatatypes)) {
|
||||||
checkResult.add(ExpressionError("builtin function argument ${arg.first.index + 1} has invalid type $argDt, expected ${arg.second.possibleDatatypes}", position))
|
checkResult.add(ExpressionError("builtin function argument ${arg.first.index + 1} has invalid type $argDt, expected ${arg.second.possibleDatatypes}", position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if(target is Subroutine) {
|
} else if(target is Subroutine) {
|
||||||
if(args.size!=target.parameters.size)
|
if(args.size!=target.parameters.size)
|
||||||
checkResult.add(SyntaxError("invalid number of arguments", position))
|
checkResult.add(SyntaxError("invalid number of arguments", position))
|
||||||
|
@ -6,6 +6,7 @@ import prog8.compiler.intermediate.IntermediateProgram
|
|||||||
import prog8.compiler.intermediate.Opcode
|
import prog8.compiler.intermediate.Opcode
|
||||||
import prog8.compiler.intermediate.Value
|
import prog8.compiler.intermediate.Value
|
||||||
import prog8.compiler.intermediate.branchOpcodes
|
import prog8.compiler.intermediate.branchOpcodes
|
||||||
|
import prog8.functions.BuiltinFunctions
|
||||||
import prog8.optimizing.same
|
import prog8.optimizing.same
|
||||||
import prog8.parser.tryGetEmbeddedResource
|
import prog8.parser.tryGetEmbeddedResource
|
||||||
import prog8.stackvm.Syscall
|
import prog8.stackvm.Syscall
|
||||||
@ -685,6 +686,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun tryConvertType(givenDt: DataType, targetDt: DataType): Boolean {
|
||||||
|
return try {
|
||||||
|
convertType(givenDt, targetDt)
|
||||||
|
true
|
||||||
|
} catch (x: CompilerException) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun convertType(givenDt: DataType, targetDt: DataType) {
|
private fun convertType(givenDt: DataType, targetDt: DataType) {
|
||||||
// only WIDENS a type, never NARROWS. To avoid loss of precision.
|
// only WIDENS a type, never NARROWS. To avoid loss of precision.
|
||||||
if(givenDt==targetDt)
|
if(givenDt==targetDt)
|
||||||
@ -784,7 +796,22 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
args.forEach { translate(it) } // place function argument(s) on the stack
|
val builtinFuncParams = BuiltinFunctions[funcname]?.parameters
|
||||||
|
args.forEachIndexed { index, arg ->
|
||||||
|
// place function argument(s) on the stack
|
||||||
|
translate(arg)
|
||||||
|
// cast type if needed
|
||||||
|
if(builtinFuncParams!=null) {
|
||||||
|
val paramDts = builtinFuncParams[index].possibleDatatypes
|
||||||
|
val argDt = arg.resultingDatatype(namespace, heap)!!
|
||||||
|
if(argDt !in paramDts) {
|
||||||
|
for(paramDt in paramDts.sorted())
|
||||||
|
if(tryConvertType(argDt, paramDt))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
when (funcname) {
|
when (funcname) {
|
||||||
"len" -> {
|
"len" -> {
|
||||||
// 1 argument, type determines the exact syscall to use
|
// 1 argument, type determines the exact syscall to use
|
||||||
|
@ -70,9 +70,17 @@ val BuiltinFunctions = mapOf(
|
|||||||
"clear_irqd" to FunctionSignature(false, emptyList(), null),
|
"clear_irqd" to FunctionSignature(false, emptyList(), null),
|
||||||
"swap" to FunctionSignature(false, listOf(BuiltinFunctionParam("first", NumericDatatypes), BuiltinFunctionParam("second", NumericDatatypes)), null),
|
"swap" to FunctionSignature(false, listOf(BuiltinFunctionParam("first", NumericDatatypes), BuiltinFunctionParam("second", NumericDatatypes)), null),
|
||||||
"memcopy" to FunctionSignature(false, listOf(
|
"memcopy" to FunctionSignature(false, listOf(
|
||||||
BuiltinFunctionParam("from", IntegerDatatypes + IterableDatatypes),
|
BuiltinFunctionParam("from", IterableDatatypes + setOf(DataType.UWORD)),
|
||||||
BuiltinFunctionParam("to", IntegerDatatypes + IterableDatatypes),
|
BuiltinFunctionParam("to", IterableDatatypes + setOf(DataType.UWORD)),
|
||||||
BuiltinFunctionParam("numbytes", IntegerDatatypes)), null),
|
BuiltinFunctionParam("numbytes", IntegerDatatypes)), null),
|
||||||
|
"memset" to FunctionSignature(false, listOf(
|
||||||
|
BuiltinFunctionParam("address", IterableDatatypes + setOf(DataType.UWORD)),
|
||||||
|
BuiltinFunctionParam("numbytes", setOf(DataType.UWORD)),
|
||||||
|
BuiltinFunctionParam("bytevalue", setOf(DataType.UBYTE, DataType.BYTE))), null),
|
||||||
|
"memsetw" to FunctionSignature(false, listOf(
|
||||||
|
BuiltinFunctionParam("address", IterableDatatypes + setOf(DataType.UWORD)),
|
||||||
|
BuiltinFunctionParam("numwords", setOf(DataType.UWORD)),
|
||||||
|
BuiltinFunctionParam("wordvalue", setOf(DataType.UWORD, DataType.WORD))), null),
|
||||||
"vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), 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_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null),
|
||||||
"vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), null),
|
"vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), null),
|
||||||
|
@ -78,7 +78,9 @@ enum class Syscall(val callNr: Short) {
|
|||||||
FUNC_SUM_UW(132),
|
FUNC_SUM_UW(132),
|
||||||
FUNC_SUM_W(133),
|
FUNC_SUM_W(133),
|
||||||
FUNC_SUM_F(134),
|
FUNC_SUM_F(134),
|
||||||
FUNC_MEMCOPY(138)
|
FUNC_MEMCOPY(138),
|
||||||
|
FUNC_MEMSET(139),
|
||||||
|
FUNC_MEMSETW(140)
|
||||||
|
|
||||||
// note: not all builtin functions of the Prog8 language are present as functions:
|
// 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)!
|
// some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL_BYTE, ROR, ROL2, ROR2, and FLT)!
|
||||||
@ -1755,8 +1757,33 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
val from = evalstack.pop().integerValue()
|
val from = evalstack.pop().integerValue()
|
||||||
mem.copy(from, to, numbytes)
|
mem.copy(from, to, numbytes)
|
||||||
}
|
}
|
||||||
|
Syscall.FUNC_MEMSET -> {
|
||||||
|
val value = evalstack.pop()
|
||||||
|
val address = evalstack.pop().integerValue()
|
||||||
|
val numbytes = evalstack.pop().integerValue()
|
||||||
|
val bytevalue = value.integerValue().toShort()
|
||||||
|
when {
|
||||||
|
value.type==DataType.UBYTE -> for(addr in address until address+numbytes)
|
||||||
|
mem.setUByte(addr, bytevalue)
|
||||||
|
value.type==DataType.BYTE -> for(addr in address until address+numbytes)
|
||||||
|
mem.setSByte(addr, bytevalue)
|
||||||
|
else -> throw VmExecutionException("(u)byte value expected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Syscall.FUNC_MEMSETW -> {
|
||||||
|
val value = evalstack.pop()
|
||||||
|
val address = evalstack.pop().integerValue()
|
||||||
|
val numwords = evalstack.pop().integerValue()
|
||||||
|
val wordvalue = value.integerValue()
|
||||||
|
when {
|
||||||
|
value.type==DataType.UWORD -> for(addr in address until address+numwords*2 step 2)
|
||||||
|
mem.setUWord(addr, wordvalue)
|
||||||
|
value.type==DataType.WORD -> for(addr in address until address+numwords*2 step 2)
|
||||||
|
mem.setSWord(addr, wordvalue)
|
||||||
|
else -> throw VmExecutionException("(u)word value expected")
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
fun irq(timestamp: Long) {
|
fun irq(timestamp: Long) {
|
||||||
// 60hz IRQ handling
|
// 60hz IRQ handling
|
||||||
|
@ -663,6 +663,17 @@ memcopy(from, to, numbytes)
|
|||||||
Because this function imposes some overhead to handle the parameters,
|
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.
|
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.
|
Compare the generated code to see if it was beneficial or not.
|
||||||
|
The most efficient will always be to write a specialized copy routine in assembly yourself!
|
||||||
|
|
||||||
|
memset(address, numbytes, bytevalue)
|
||||||
|
Efficiently set a part of memory to the given (u)byte value.
|
||||||
|
But the most efficient will always be to write a specialized fill routine in assembly yourself!
|
||||||
|
Note that for clearing the character screen, very fast specialized subroutines are
|
||||||
|
available in the ``c64scr`` block (part of the ``c64utils`` module)
|
||||||
|
|
||||||
|
memsetw(address, numwords, wordvalue)
|
||||||
|
Efficiently set a part of memory to the given (u)word value.
|
||||||
|
But the most efficient will always be to write a specialized fill routine in assembly yourself!
|
||||||
|
|
||||||
swap(x, y)
|
swap(x, y)
|
||||||
Swap the values of numerical variables (or memory locations) x and y in a fast way.
|
Swap the values of numerical variables (or memory locations) x and y in a fast way.
|
||||||
|
@ -5,26 +5,11 @@
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
; memset($0400, $0400+40, 81)
|
memset($0400+40*3, 40*8, 81)
|
||||||
|
memsetw($0400+40*12, 8*40/2, $80a0)
|
||||||
|
memset($0400, 20, 33)
|
||||||
|
memcopy($0400, $0400+121, 20)
|
||||||
|
|
||||||
A=99
|
|
||||||
if(A<99) goto first else goto second
|
|
||||||
|
|
||||||
first:
|
|
||||||
c64scr.print("a<99 !\n")
|
|
||||||
goto next
|
|
||||||
second:
|
|
||||||
c64scr.print("wrong: a>=99 ?!\n")
|
|
||||||
|
|
||||||
next:
|
|
||||||
A=99
|
|
||||||
if(A<99) goto first2 else {
|
|
||||||
c64scr.print("wrong: a>=99 ?!\n")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
|
|
||||||
first2:
|
|
||||||
c64scr.print("a<99 !\n")
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user