mirror of
https://github.com/irmen/prog8.git
synced 2025-02-22 16:29:05 +00:00
remove support for array-to-array assignments (other than initialization of variable declaration)
Just use an explicit sys.memcopy(src, dest, sizeof(dest)) or assign array members individually.
This commit is contained in:
parent
aef211e5f3
commit
e9edffa9f0
@ -79,7 +79,6 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
|||||||
// cmp returns a status in the carry flag, but not a proper return value
|
// cmp returns a status in the carry flag, but not a proper return value
|
||||||
"cmp" to FSignature(false, listOf(FParam("value1", IntegerDatatypes), FParam("value2", NumericDatatypes)), null),
|
"cmp" to FSignature(false, listOf(FParam("value1", IntegerDatatypes), FParam("value2", NumericDatatypes)), null),
|
||||||
"prog8_lib_stringcompare" to FSignature(true, listOf(FParam("str1", arrayOf(DataType.STR)), FParam("str2", arrayOf(DataType.STR))), DataType.BYTE),
|
"prog8_lib_stringcompare" to FSignature(true, listOf(FParam("str1", arrayOf(DataType.STR)), FParam("str2", arrayOf(DataType.STR))), DataType.BYTE),
|
||||||
"prog8_lib_arraycopy" to FSignature(false, listOf(FParam("source", ArrayDatatypes), FParam("target", ArrayDatatypes)), null),
|
|
||||||
"prog8_lib_square_byte" to FSignature(true, listOf(FParam("value", arrayOf(DataType.BYTE, DataType.UBYTE))), DataType.UBYTE),
|
"prog8_lib_square_byte" to FSignature(true, listOf(FParam("value", arrayOf(DataType.BYTE, DataType.UBYTE))), DataType.UBYTE),
|
||||||
"prog8_lib_square_word" to FSignature(true, listOf(FParam("value", arrayOf(DataType.WORD, DataType.UWORD))), DataType.UWORD),
|
"prog8_lib_square_word" to FSignature(true, listOf(FParam("value", arrayOf(DataType.WORD, DataType.UWORD))), DataType.UWORD),
|
||||||
"prog8_ifelse_bittest_set" to FSignature(true, listOf(FParam("variable", ByteDatatypes), FParam("bitnumber", arrayOf(DataType.UBYTE))), DataType.BOOL),
|
"prog8_ifelse_bittest_set" to FSignature(true, listOf(FParam("variable", ByteDatatypes), FParam("bitnumber", arrayOf(DataType.UBYTE))), DataType.BOOL),
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package prog8.codegen.cpu6502
|
package prog8.codegen.cpu6502
|
||||||
|
|
||||||
import prog8.code.StMemVar
|
|
||||||
import prog8.code.StStaticVariable
|
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.codegen.cpu6502.assignment.*
|
import prog8.codegen.cpu6502.assignment.*
|
||||||
@ -71,101 +69,12 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
"prog8_lib_stringcompare" -> funcStringCompare(fcall, resultRegister)
|
"prog8_lib_stringcompare" -> funcStringCompare(fcall, resultRegister)
|
||||||
"prog8_lib_square_byte" -> funcSquare(fcall, DataType.UBYTE, resultRegister)
|
"prog8_lib_square_byte" -> funcSquare(fcall, DataType.UBYTE, resultRegister)
|
||||||
"prog8_lib_square_word" -> funcSquare(fcall, DataType.UWORD, resultRegister)
|
"prog8_lib_square_word" -> funcSquare(fcall, DataType.UWORD, resultRegister)
|
||||||
"prog8_lib_arraycopy" -> funcArrayCopy(fcall)
|
|
||||||
else -> throw AssemblyError("missing asmgen for builtin func ${fcall.name}")
|
else -> throw AssemblyError("missing asmgen for builtin func ${fcall.name}")
|
||||||
}
|
}
|
||||||
|
|
||||||
return BuiltinFunctions.getValue(fcall.name).returnType
|
return BuiltinFunctions.getValue(fcall.name).returnType
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcArrayCopy(fcall: PtBuiltinFunctionCall) {
|
|
||||||
val source = fcall.args[0] as PtIdentifier
|
|
||||||
val target = fcall.args[1] as PtIdentifier
|
|
||||||
|
|
||||||
val numElements = when(val sourceSymbol = asmgen.symbolTable.lookup(source.name)) {
|
|
||||||
is StStaticVariable -> sourceSymbol.length!!
|
|
||||||
is StMemVar -> sourceSymbol.length!!
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
val sourceAsm = asmgen.asmVariableName(source)
|
|
||||||
val targetAsm = asmgen.asmVariableName(target)
|
|
||||||
|
|
||||||
if(source.type in SplitWordArrayTypes && target.type in SplitWordArrayTypes) {
|
|
||||||
// split -> split words (copy lsb and msb arrays separately)
|
|
||||||
asmgen.out("""
|
|
||||||
lda #<${sourceAsm}_lsb
|
|
||||||
ldy #>${sourceAsm}_lsb
|
|
||||||
sta P8ZP_SCRATCH_W1
|
|
||||||
sty P8ZP_SCRATCH_W1+1
|
|
||||||
lda #<${targetAsm}_lsb
|
|
||||||
ldy #>${targetAsm}_lsb
|
|
||||||
sta P8ZP_SCRATCH_W2
|
|
||||||
sty P8ZP_SCRATCH_W2+1
|
|
||||||
ldy #${numElements and 255}
|
|
||||||
jsr prog8_lib.memcopy_small
|
|
||||||
lda #<${sourceAsm}_msb
|
|
||||||
ldy #>${sourceAsm}_msb
|
|
||||||
sta P8ZP_SCRATCH_W1
|
|
||||||
sty P8ZP_SCRATCH_W1+1
|
|
||||||
lda #<${targetAsm}_msb
|
|
||||||
ldy #>${targetAsm}_msb
|
|
||||||
sta P8ZP_SCRATCH_W2
|
|
||||||
sty P8ZP_SCRATCH_W2+1
|
|
||||||
ldy #${numElements and 255}
|
|
||||||
jsr prog8_lib.memcopy_small""")
|
|
||||||
}
|
|
||||||
else if(source.type in SplitWordArrayTypes) {
|
|
||||||
// split word array to normal word array (copy lsb and msb arrays separately)
|
|
||||||
require(target.type==DataType.ARRAY_UW || target.type==DataType.ARRAY_W)
|
|
||||||
asmgen.out("""
|
|
||||||
lda #<${sourceAsm}_lsb
|
|
||||||
ldy #>${sourceAsm}_lsb
|
|
||||||
sta P8ZP_SCRATCH_W1
|
|
||||||
sty P8ZP_SCRATCH_W1+1
|
|
||||||
lda #<${sourceAsm}_msb
|
|
||||||
ldy #>${sourceAsm}_msb
|
|
||||||
sta P8ZP_SCRATCH_W2
|
|
||||||
sty P8ZP_SCRATCH_W2+1
|
|
||||||
lda #<${targetAsm}
|
|
||||||
ldy #>${targetAsm}
|
|
||||||
ldx #${numElements and 255}
|
|
||||||
jsr prog8_lib.arraycopy_split_to_normal_words""")
|
|
||||||
}
|
|
||||||
else if(target.type in SplitWordArrayTypes) {
|
|
||||||
// normal word array to split array
|
|
||||||
require(source.type==DataType.ARRAY_UW || source.type==DataType.ARRAY_W)
|
|
||||||
asmgen.out("""
|
|
||||||
lda #<${targetAsm}_lsb
|
|
||||||
ldy #>${targetAsm}_lsb
|
|
||||||
sta P8ZP_SCRATCH_W1
|
|
||||||
sty P8ZP_SCRATCH_W1+1
|
|
||||||
lda #<${targetAsm}_msb
|
|
||||||
ldy #>${targetAsm}_msb
|
|
||||||
sta P8ZP_SCRATCH_W2
|
|
||||||
sty P8ZP_SCRATCH_W2+1
|
|
||||||
lda #<${sourceAsm}
|
|
||||||
ldy #>${sourceAsm}
|
|
||||||
ldx #${numElements and 255}
|
|
||||||
jsr prog8_lib.arraycopy_normal_to_split_words""")
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// normal array to array copy, various element types
|
|
||||||
val eltsize = asmgen.options.compTarget.memorySize(ArrayToElementTypes.getValue(source.type))
|
|
||||||
val numBytes = numElements * eltsize
|
|
||||||
asmgen.out("""
|
|
||||||
lda #<${sourceAsm}
|
|
||||||
ldy #>${sourceAsm}
|
|
||||||
sta P8ZP_SCRATCH_W1
|
|
||||||
sty P8ZP_SCRATCH_W1+1
|
|
||||||
lda #<${targetAsm}
|
|
||||||
ldy #>${targetAsm}
|
|
||||||
sta P8ZP_SCRATCH_W2
|
|
||||||
sty P8ZP_SCRATCH_W2+1
|
|
||||||
ldy #${numBytes and 255}
|
|
||||||
jsr prog8_lib.memcopy_small""")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun funcSquare(fcall: PtBuiltinFunctionCall, resultType: DataType, resultRegister: RegisterOrPair?) {
|
private fun funcSquare(fcall: PtBuiltinFunctionCall, resultType: DataType, resultRegister: RegisterOrPair?) {
|
||||||
// square of word value is faster with dedicated routine, square of byte just use the regular multiplication routine.
|
// square of word value is faster with dedicated routine, square of byte just use the regular multiplication routine.
|
||||||
when (resultType) {
|
when (resultType) {
|
||||||
@ -1357,22 +1266,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun outputAddressAndLengthOfArray(arg: PtIdentifier) {
|
|
||||||
// address goes in P8ZP_SCRATCH_W1, number of elements in A
|
|
||||||
val numElements = when(val symbol = asmgen.symbolTable.lookup(arg.name)) {
|
|
||||||
is StStaticVariable -> symbol.length!!
|
|
||||||
is StMemVar -> symbol.length!!
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
val identifierName = asmgen.asmVariableName(arg)
|
|
||||||
asmgen.out("""
|
|
||||||
lda #<$identifierName
|
|
||||||
ldy #>$identifierName
|
|
||||||
sta P8ZP_SCRATCH_W1
|
|
||||||
sty P8ZP_SCRATCH_W1+1
|
|
||||||
lda #${numElements and 255}""")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun translateArguments(call: PtBuiltinFunctionCall, scope: IPtSubroutine?) {
|
private fun translateArguments(call: PtBuiltinFunctionCall, scope: IPtSubroutine?) {
|
||||||
val signature = BuiltinFunctions.getValue(call.name)
|
val signature = BuiltinFunctions.getValue(call.name)
|
||||||
val callConv = signature.callConvention(call.args.map { it.type})
|
val callConv = signature.callConvention(call.args.map { it.type})
|
||||||
|
@ -44,72 +44,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
"prog8_lib_stringcompare" -> funcStringCompare(call)
|
"prog8_lib_stringcompare" -> funcStringCompare(call)
|
||||||
"prog8_lib_square_byte" -> funcSquare(call, IRDataType.BYTE)
|
"prog8_lib_square_byte" -> funcSquare(call, IRDataType.BYTE)
|
||||||
"prog8_lib_square_word" -> funcSquare(call, IRDataType.WORD)
|
"prog8_lib_square_word" -> funcSquare(call, IRDataType.WORD)
|
||||||
"prog8_lib_arraycopy" -> funcArrayCopy(call)
|
|
||||||
else -> throw AssemblyError("missing builtinfunc for ${call.name}")
|
else -> throw AssemblyError("missing builtinfunc for ${call.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcArrayCopy(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
|
||||||
val source = call.args[0] as PtIdentifier
|
|
||||||
val target = call.args[1] as PtIdentifier
|
|
||||||
val sourceLength = codeGen.symbolTable.getLength(source.name)!!
|
|
||||||
val targetLength = codeGen.symbolTable.getLength(target.name)!!
|
|
||||||
require(sourceLength==targetLength)
|
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
|
||||||
val fromReg = codeGen.registers.nextFree()
|
|
||||||
val toReg = codeGen.registers.nextFree()
|
|
||||||
val countReg = codeGen.registers.nextFree()
|
|
||||||
if(source.type in SplitWordArrayTypes && target.type in SplitWordArrayTypes) {
|
|
||||||
// split words -> split words, copy lsb and msb arrays separately
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=fromReg, labelSymbol = source.name+"_lsb")
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=toReg, labelSymbol = target.name+"_lsb")
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=countReg, immediate = sourceLength)
|
|
||||||
it += codeGen.makeSyscall(IMSyscall.MEMCOPY_SMALL, listOf(IRDataType.WORD to fromReg, IRDataType.WORD to toReg, IRDataType.BYTE to (countReg and 255)), returns = null)
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=fromReg, labelSymbol = source.name+"_msb")
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=toReg, labelSymbol = target.name+"_msb")
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=countReg, immediate = sourceLength)
|
|
||||||
it += codeGen.makeSyscall(IMSyscall.MEMCOPY_SMALL, listOf(IRDataType.WORD to fromReg, IRDataType.WORD to toReg, IRDataType.BYTE to (countReg and 255)), returns = null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(source.type in SplitWordArrayTypes) {
|
|
||||||
// split -> normal words
|
|
||||||
require(target.type==DataType.ARRAY_UW || target.type==DataType.ARRAY_W)
|
|
||||||
val fromRegMsb = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=fromReg, labelSymbol = source.name+"_lsb")
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=fromRegMsb, labelSymbol = source.name+"_msb")
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=toReg, labelSymbol = target.name)
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=countReg, immediate = sourceLength)
|
|
||||||
}
|
|
||||||
result += codeGen.makeSyscall(IMSyscall.ARRAYCOPY_SPLITW_TO_NORMAL, listOf(IRDataType.WORD to fromReg, IRDataType.WORD to fromRegMsb, IRDataType.WORD to toReg, IRDataType.BYTE to countReg), returns = null)
|
|
||||||
}
|
|
||||||
else if(target.type in SplitWordArrayTypes) {
|
|
||||||
// normal -> split words
|
|
||||||
require(source.type==DataType.ARRAY_UW || source.type==DataType.ARRAY_W)
|
|
||||||
val toRegMsb = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=fromReg, labelSymbol = source.name)
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=toReg, labelSymbol = target.name+"_lsb")
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=toRegMsb, labelSymbol = target.name+"_msb")
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=countReg, immediate = sourceLength)
|
|
||||||
}
|
|
||||||
result += codeGen.makeSyscall(IMSyscall.ARRAYCOPY_NORMAL_TO_SPLITW, listOf(IRDataType.WORD to fromReg, IRDataType.WORD to toReg, IRDataType.WORD to toRegMsb, IRDataType.BYTE to countReg), returns = null)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// normal array to array copy (various element types)
|
|
||||||
val eltsize = codeGen.options.compTarget.memorySize(ArrayToElementTypes.getValue(source.type))
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=fromReg, labelSymbol = source.name)
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=toReg, labelSymbol = target.name)
|
|
||||||
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=countReg, immediate = sourceLength * eltsize)
|
|
||||||
}
|
|
||||||
result += codeGen.makeSyscall(IMSyscall.MEMCOPY_SMALL, listOf(IRDataType.WORD to fromReg, IRDataType.WORD to toReg, IRDataType.BYTE to (countReg and 255)), returns = null)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ExpressionCodeResult(result, IRDataType.BYTE, -1, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun funcSquare(call: PtBuiltinFunctionCall, resultType: IRDataType): ExpressionCodeResult {
|
private fun funcSquare(call: PtBuiltinFunctionCall, resultType: IRDataType): ExpressionCodeResult {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val valueTr = exprGen.translateExpression(call.args[0])
|
val valueTr = exprGen.translateExpression(call.args[0])
|
||||||
|
@ -1813,14 +1813,9 @@ internal class AstChecker(private val program: Program,
|
|||||||
sourceValue: Expression) : Boolean {
|
sourceValue: Expression) : Boolean {
|
||||||
val position = sourceValue.position
|
val position = sourceValue.position
|
||||||
|
|
||||||
if(sourceValue is ArrayLiteral && targetDatatype in ArrayDatatypes) {
|
if(sourceValue is ArrayLiteral || targetDatatype in ArrayDatatypes) {
|
||||||
val vardecl=target.identifier?.targetVarDecl(program)
|
errors.err("cannot assign arrays directly. Maybe use sys.memcopy(src, tgt, sizeof(tgt)) instead.", target.position)
|
||||||
val targetSize = vardecl?.arraysize?.constIndex()
|
return false
|
||||||
if(targetSize!=null) {
|
|
||||||
if(sourceValue.value.size != targetSize) {
|
|
||||||
errors.err("array size mismatch (expecting $targetSize, got ${sourceValue.value.size})", sourceValue.position)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sourceValue is RangeExpression) {
|
if(sourceValue is RangeExpression) {
|
||||||
@ -1841,7 +1836,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
DataType.UWORD -> sourceDatatype == DataType.UBYTE || sourceDatatype == DataType.UWORD
|
DataType.UWORD -> sourceDatatype == DataType.UBYTE || sourceDatatype == DataType.UWORD
|
||||||
DataType.FLOAT -> sourceDatatype in NumericDatatypes
|
DataType.FLOAT -> sourceDatatype in NumericDatatypes
|
||||||
DataType.STR -> sourceDatatype == DataType.STR
|
DataType.STR -> sourceDatatype == DataType.STR
|
||||||
else -> targetDatatype in ArrayDatatypes && sourceValue is ArrayLiteral
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
|
@ -23,22 +23,6 @@ internal class CodeDesugarer(val program: Program, private val errors: IErrorRep
|
|||||||
// - pointer[word] replaced by @(pointer+word)
|
// - pointer[word] replaced by @(pointer+word)
|
||||||
// - @(&var) and @(&var+1) replaced by lsb(var) and msb(var) if var is a word
|
// - @(&var) and @(&var+1) replaced by lsb(var) and msb(var) if var is a word
|
||||||
// - flatten chained assignments
|
// - flatten chained assignments
|
||||||
// - replace array assignments by a call to the builtin function that does this: prog8_lib_arraycopy
|
|
||||||
|
|
||||||
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
|
||||||
val targetArray = assignment.target.identifier?.targetVarDecl(program)
|
|
||||||
val sourceArray = (assignment.value as? IdentifierReference)?.targetVarDecl(program)
|
|
||||||
if(targetArray?.isArray==true && sourceArray?.isArray==true) {
|
|
||||||
val copy = FunctionCallStatement(
|
|
||||||
IdentifierReference(listOf("prog8_lib_arraycopy"), assignment.position),
|
|
||||||
mutableListOf(
|
|
||||||
IdentifierReference(sourceArray.scopedName, assignment.position),
|
|
||||||
IdentifierReference(targetArray.scopedName, assignment.position)
|
|
||||||
), false, assignment.position)
|
|
||||||
return listOf(IAstModification.ReplaceNode(assignment, copy, parent))
|
|
||||||
}
|
|
||||||
return noModifications
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> {
|
override fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> {
|
||||||
fun jumpAfter(stmt: Statement): Iterable<IAstModification> {
|
fun jumpAfter(stmt: Statement): Iterable<IAstModification> {
|
||||||
|
@ -5,10 +5,7 @@ import io.kotest.matchers.shouldBe
|
|||||||
import io.kotest.matchers.shouldNotBe
|
import io.kotest.matchers.shouldNotBe
|
||||||
import io.kotest.matchers.string.shouldContain
|
import io.kotest.matchers.string.shouldContain
|
||||||
import io.kotest.matchers.types.instanceOf
|
import io.kotest.matchers.types.instanceOf
|
||||||
import prog8.code.StStaticVariable
|
|
||||||
import prog8.code.SymbolTableMaker
|
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.*
|
|
||||||
import prog8.code.target.C64Target
|
import prog8.code.target.C64Target
|
||||||
import prog8.code.target.VMTarget
|
import prog8.code.target.VMTarget
|
||||||
import prog8tests.helpers.ErrorReporterForTests
|
import prog8tests.helpers.ErrorReporterForTests
|
||||||
@ -156,25 +153,6 @@ main {
|
|||||||
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
test("split array assignments") {
|
|
||||||
val text = """
|
|
||||||
main {
|
|
||||||
sub start() {
|
|
||||||
str name1 = "name1"
|
|
||||||
str name2 = "name2"
|
|
||||||
uword[] @split names = [name1, name2, "name3"]
|
|
||||||
uword[] @split names2 = [name1, name2, "name3"]
|
|
||||||
uword[] addresses = [0,0,0]
|
|
||||||
names = [1111,2222,3333]
|
|
||||||
addresses = names
|
|
||||||
names = addresses
|
|
||||||
names2 = names
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
|
|
||||||
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
|
||||||
}
|
|
||||||
|
|
||||||
test("array target with expression for index") {
|
test("array target with expression for index") {
|
||||||
val text = """
|
val text = """
|
||||||
main {
|
main {
|
||||||
@ -333,81 +311,6 @@ main {
|
|||||||
errors.errors[2] shouldContain "out of bounds"
|
errors.errors[2] shouldContain "out of bounds"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("array assignments should check for number of elements and element type correctness") {
|
|
||||||
val src="""
|
|
||||||
%option enable_floats
|
|
||||||
|
|
||||||
main {
|
|
||||||
sub start() {
|
|
||||||
ubyte[] array = 1 to 4
|
|
||||||
ubyte[] array2 = [1,2,3,4]
|
|
||||||
str[] names = ["apple", "banana", "tomato"]
|
|
||||||
|
|
||||||
array = [10,11,12,13] ; ok!
|
|
||||||
array = 20 to 23 ; ok!
|
|
||||||
names = ["x1", "x2", "x3"] ; ok!
|
|
||||||
|
|
||||||
ubyte[] array3 = [1,2,3,4000] ; error: element type
|
|
||||||
array = 10 to 15 ; error: array size
|
|
||||||
array = 1000 to 1003 ; error: element type
|
|
||||||
names = ["x1", "x2", "x3", "x4"] ; error: array size
|
|
||||||
names = [1.1, 2.2, 3.3, 4.4] ; error: array size AND element type
|
|
||||||
names = [1.1, 2.2, 999999.9] ; error: element type
|
|
||||||
names = [1.1, 2.2, 9.9] ; error: element type
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
val errors = ErrorReporterForTests()
|
|
||||||
compileText(C64Target(), false, src, writeAssembly = true, errors = errors) shouldBe null
|
|
||||||
errors.errors.size shouldBe 8
|
|
||||||
errors.errors[0] shouldContain "incompatible type"
|
|
||||||
errors.errors[1] shouldContain "array size mismatch"
|
|
||||||
errors.errors[2] shouldContain "array element out of range"
|
|
||||||
errors.errors[3] shouldContain "array size mismatch"
|
|
||||||
errors.errors[4] shouldContain "array size mismatch"
|
|
||||||
errors.errors[5] shouldContain "value has incompatible type"
|
|
||||||
errors.errors[6] shouldContain "value has incompatible type"
|
|
||||||
errors.errors[7] shouldContain "value has incompatible type"
|
|
||||||
}
|
|
||||||
|
|
||||||
test("array assignments should work via array copy call") {
|
|
||||||
val src="""
|
|
||||||
%option enable_floats
|
|
||||||
|
|
||||||
main {
|
|
||||||
sub start() {
|
|
||||||
ubyte[] array = [1,2,3]
|
|
||||||
ubyte[3] array2
|
|
||||||
float[] flarray = [1.1, 2.2, 3.3]
|
|
||||||
float[3] flarray2
|
|
||||||
word[] warray = [-2222,42,3333]
|
|
||||||
word[3] warray2
|
|
||||||
str[] names = ["apple", "banana", "tomato"]
|
|
||||||
str[3] names2
|
|
||||||
|
|
||||||
; 8 array assignments -> 8 arraycopies:
|
|
||||||
array = [8,7,6]
|
|
||||||
array = array2
|
|
||||||
flarray = [99.9, 88.8, 77.7]
|
|
||||||
flarray = flarray2
|
|
||||||
warray = [4444,5555,6666]
|
|
||||||
warray = warray2
|
|
||||||
names = ["x1", "x2", "x3"]
|
|
||||||
names = names2
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
compileText(VMTarget(), false, src, writeAssembly = true) shouldNotBe null
|
|
||||||
val result = compileText(C64Target(), false, src, writeAssembly = true)!!
|
|
||||||
val x = result.codegenAst!!.entrypoint()!!
|
|
||||||
(x.children[12] as PtBuiltinFunctionCall).name shouldBe "prog8_lib_arraycopy"
|
|
||||||
(x.children[13] as PtBuiltinFunctionCall).name shouldBe "prog8_lib_arraycopy"
|
|
||||||
(x.children[14] as PtBuiltinFunctionCall).name shouldBe "prog8_lib_arraycopy"
|
|
||||||
(x.children[15] as PtBuiltinFunctionCall).name shouldBe "prog8_lib_arraycopy"
|
|
||||||
(x.children[16] as PtBuiltinFunctionCall).name shouldBe "prog8_lib_arraycopy"
|
|
||||||
(x.children[17] as PtBuiltinFunctionCall).name shouldBe "prog8_lib_arraycopy"
|
|
||||||
(x.children[18] as PtBuiltinFunctionCall).name shouldBe "prog8_lib_arraycopy"
|
|
||||||
(x.children[19] as PtBuiltinFunctionCall).name shouldBe "prog8_lib_arraycopy"
|
|
||||||
}
|
|
||||||
|
|
||||||
test("array and string initializer with multiplication") {
|
test("array and string initializer with multiplication") {
|
||||||
val src="""
|
val src="""
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
@ -497,89 +400,5 @@ label:
|
|||||||
errors.errors[0] shouldContain "contains non-constant"
|
errors.errors[0] shouldContain "contains non-constant"
|
||||||
errors.errors[1] shouldContain "contains non-constant"
|
errors.errors[1] shouldContain "contains non-constant"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTestOptions(): CompilationOptions {
|
|
||||||
val target = VMTarget()
|
|
||||||
return CompilationOptions(
|
|
||||||
OutputType.RAW,
|
|
||||||
CbmPrgLauncherType.NONE,
|
|
||||||
ZeropageType.DONTUSE,
|
|
||||||
zpReserved = emptyList(),
|
|
||||||
zpAllowed = CompilationOptions.AllZeropageAllowed,
|
|
||||||
floats = true,
|
|
||||||
noSysInit = false,
|
|
||||||
compTarget = target,
|
|
||||||
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
test("array assignments with ranges and multiplications") {
|
|
||||||
val src="""
|
|
||||||
%option enable_floats
|
|
||||||
|
|
||||||
main {
|
|
||||||
sub start() {
|
|
||||||
bool[4] boolarray3
|
|
||||||
ubyte[4] bytearray3
|
|
||||||
uword[4] wordarray3
|
|
||||||
float[4] floatarray3
|
|
||||||
|
|
||||||
boolarray3 = [true] *4
|
|
||||||
bytearray3 = [42]*4
|
|
||||||
wordarray3 = [999]*4
|
|
||||||
wordarray3 = [&bytearray3]*4
|
|
||||||
wordarray3 = [bytearray3]*4
|
|
||||||
floatarray3 = [99.77]*4
|
|
||||||
|
|
||||||
bytearray3 = 10 to 13
|
|
||||||
wordarray3 = 5000 to 5003
|
|
||||||
floatarray3 = 100 to 103
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
val ast = compileText(C64Target(), false, src, writeAssembly = true)!!.codegenAst!!
|
|
||||||
val x = ast.entrypoint()!!
|
|
||||||
x.children.size shouldBe 23
|
|
||||||
val assign1value = (x.children[13] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val assign2value = (x.children[14] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val assign3value = (x.children[15] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val assign4value = (x.children[16] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val assign5value = (x.children[17] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val assign6value = (x.children[18] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val assign7value = (x.children[19] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val assign8value = (x.children[20] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val assign9value = (x.children[21] as PtBuiltinFunctionCall).args[1]
|
|
||||||
val options = getTestOptions()
|
|
||||||
val st = SymbolTableMaker(ast, options).make()
|
|
||||||
|
|
||||||
val heapvar1 = st.lookup((assign1value as PtIdentifier).name) as StStaticVariable
|
|
||||||
val heapvar2 = st.lookup((assign2value as PtIdentifier).name) as StStaticVariable
|
|
||||||
val heapvar3 = st.lookup((assign3value as PtIdentifier).name) as StStaticVariable
|
|
||||||
val heapvar4 = st.lookup((assign4value as PtIdentifier).name) as StStaticVariable
|
|
||||||
val heapvar5 = st.lookup((assign5value as PtIdentifier).name) as StStaticVariable
|
|
||||||
val heapvar6 = st.lookup((assign6value as PtIdentifier).name) as StStaticVariable
|
|
||||||
val heapvar7 = st.lookup((assign7value as PtIdentifier).name) as StStaticVariable
|
|
||||||
val heapvar8 = st.lookup((assign8value as PtIdentifier).name) as StStaticVariable
|
|
||||||
val heapvar9 = st.lookup((assign9value as PtIdentifier).name) as StStaticVariable
|
|
||||||
heapvar1.length shouldBe 4
|
|
||||||
heapvar2.length shouldBe 4
|
|
||||||
heapvar3.length shouldBe 4
|
|
||||||
heapvar4.length shouldBe 4
|
|
||||||
heapvar5.length shouldBe 4
|
|
||||||
heapvar6.length shouldBe 4
|
|
||||||
heapvar7.length shouldBe 4
|
|
||||||
heapvar8.length shouldBe 4
|
|
||||||
heapvar9.length shouldBe 4
|
|
||||||
heapvar1.dt shouldBe DataType.ARRAY_BOOL
|
|
||||||
heapvar2.dt shouldBe DataType.ARRAY_UB
|
|
||||||
heapvar3.dt shouldBe DataType.ARRAY_UW
|
|
||||||
heapvar4.dt shouldBe DataType.ARRAY_UW
|
|
||||||
heapvar5.dt shouldBe DataType.ARRAY_UW
|
|
||||||
heapvar6.dt shouldBe DataType.ARRAY_F
|
|
||||||
heapvar7.dt shouldBe DataType.ARRAY_UB
|
|
||||||
heapvar8.dt shouldBe DataType.ARRAY_UW
|
|
||||||
heapvar9.dt shouldBe DataType.ARRAY_F
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import io.kotest.matchers.shouldBe
|
|||||||
import io.kotest.matchers.shouldNotBe
|
import io.kotest.matchers.shouldNotBe
|
||||||
import io.kotest.matchers.string.shouldContain
|
import io.kotest.matchers.string.shouldContain
|
||||||
import prog8.code.target.C64Target
|
import prog8.code.target.C64Target
|
||||||
import prog8.code.target.VMTarget
|
|
||||||
import prog8tests.helpers.ErrorReporterForTests
|
import prog8tests.helpers.ErrorReporterForTests
|
||||||
import prog8tests.helpers.compileText
|
import prog8tests.helpers.compileText
|
||||||
|
|
||||||
@ -42,23 +41,6 @@ class TestVariables: FunSpec({
|
|||||||
compileText(C64Target(), true, text, writeAssembly = true) shouldNotBe null
|
compileText(C64Target(), true, text, writeAssembly = true) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
test("array initialization with array var assignment") {
|
|
||||||
val text = """
|
|
||||||
main {
|
|
||||||
sub start() {
|
|
||||||
ubyte[3] @shared arrayvar=main.values1
|
|
||||||
arrayvar = main.values2
|
|
||||||
}
|
|
||||||
|
|
||||||
ubyte[] values1 = [1,2,3]
|
|
||||||
ubyte[] values2 = [1,2,3]
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
|
||||||
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
test("pipe character in string literal") {
|
test("pipe character in string literal") {
|
||||||
val text = """
|
val text = """
|
||||||
main {
|
main {
|
||||||
|
@ -299,7 +299,6 @@ always have to be constants. Here are some examples of arrays::
|
|||||||
value = array[3] ; the fourth value in the array (index is 0-based)
|
value = array[3] ; the fourth value in the array (index is 0-based)
|
||||||
char = string[4] ; the fifth character (=byte) in the string
|
char = string[4] ; the fifth character (=byte) in the string
|
||||||
char = string[-2] ; the second-to-last character in the string (Python-style indexing from the end)
|
char = string[-2] ; the second-to-last character in the string (Python-style indexing from the end)
|
||||||
flags = [false, true] ; reset all flags in the array
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Right now, the array should be small enough to be indexable by a single byte index.
|
Right now, the array should be small enough to be indexable by a single byte index.
|
||||||
@ -309,14 +308,16 @@ always have to be constants. Here are some examples of arrays::
|
|||||||
Arrays can be initialized with a range expression or an array literal value.
|
Arrays can be initialized with a range expression or an array literal value.
|
||||||
You can write out such an initializer value over several lines if you want to improve readability.
|
You can write out such an initializer value over several lines if you want to improve readability.
|
||||||
|
|
||||||
|
You can assign a new value to an element in the array, but you can't assign a whole
|
||||||
|
new array to another array at once. This is usually a costly operation. If you really
|
||||||
|
need this you have to write it out depending on the use case: you can copy the memory using
|
||||||
|
``sys.memcopy(sourcearray, targetarray, sizeof(targetarray))``. Or perhaps use ``sys.memset`` instead to
|
||||||
|
set it all to the same value, or maybe even simply assign the individual elements.
|
||||||
|
|
||||||
Note that the various keywords for the data type and variable type (``byte``, ``word``, ``const``, etc.)
|
Note that the various keywords for the data type and variable type (``byte``, ``word``, ``const``, etc.)
|
||||||
can't be used as *identifiers* elsewhere. You can't make a variable, block or subroutine with the name ``byte``
|
can't be used as *identifiers* elsewhere. You can't make a variable, block or subroutine with the name ``byte``
|
||||||
for instance.
|
for instance.
|
||||||
|
|
||||||
It is possible to assign an array (variable or array literal) to another array; this will overwrite all elements in the target
|
|
||||||
array with those in the source array. The number of elements in the arrays and the data types have to match.
|
|
||||||
For large arrays this is a slow operation because all values are copied over.
|
|
||||||
|
|
||||||
Using the ``in`` operator you can easily check if a value is present in an array,
|
Using the ``in`` operator you can easily check if a value is present in an array,
|
||||||
example: ``if choice in [1,2,3,4] {....}``
|
example: ``if choice in [1,2,3,4] {....}``
|
||||||
|
|
||||||
@ -378,8 +379,8 @@ You can concatenate two string literals using '+', which can be useful to
|
|||||||
split long strings over separate lines. But remember that the length
|
split long strings over separate lines. But remember that the length
|
||||||
of the total string still cannot exceed 255 characters.
|
of the total string still cannot exceed 255 characters.
|
||||||
A string literal can also be repeated a given number of times using '*', where the repeat number must be a constant value.
|
A string literal can also be repeated a given number of times using '*', where the repeat number must be a constant value.
|
||||||
And a new string value can be assigned to another string, but no bounds check is done
|
And a new string value can be assigned to another string, but no bounds check is done!
|
||||||
so be sure the destination string is large enough to contain the new value (it is overwritten in memory)::
|
So be sure the destination string is large enough to contain the new value (it is overwritten in memory)::
|
||||||
|
|
||||||
str string1 = "first part" + "second part"
|
str string1 = "first part" + "second part"
|
||||||
str string2 = "hello!" * 10
|
str string2 = "hello!" * 10
|
||||||
|
@ -511,8 +511,6 @@ the downto variant to avoid having to specify the step as well::
|
|||||||
xx = 10
|
xx = 10
|
||||||
aa to xx ; range of 5, 6, 7, 8, 9, 10
|
aa to xx ; range of 5, 6, 7, 8, 9, 10
|
||||||
|
|
||||||
byte[] array = 10 to 13 ; sets the array to [10, 11, 12, 13]
|
|
||||||
|
|
||||||
for i in 0 to 127 {
|
for i in 0 to 127 {
|
||||||
; i loops 0, 1, 2, ... 127
|
; i loops 0, 1, 2, ... 127
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- should the array-to-array assignment support be removed and instead require an explicit copy function call? What prog8_lib_arraycopy() now does. Or just use memcopy.
|
- fixup syscall list UNUSED_SYSCALL_1 and 2 (numbers shift!)
|
||||||
- should we add a cleararray builtin function that can efficiently set every element in the array to the given value
|
|
||||||
|
|
||||||
|
|
||||||
Improve register load order in subroutine call args assignments:
|
Improve register load order in subroutine call args assignments:
|
||||||
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
|
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
|
||||||
|
@ -25,7 +25,7 @@ main {
|
|||||||
for y in 32 to 199+32 {
|
for y in 32 to 199+32 {
|
||||||
cx16.FB_cursor_position((320-len(cells))/2,y)
|
cx16.FB_cursor_position((320-len(cells))/2,y)
|
||||||
cx16.FB_set_pixels(cells, len(cells))
|
cx16.FB_set_pixels(cells, len(cells))
|
||||||
cells_previous = cells
|
sys.memcopy(cells, cells_previous, sizeof(cells))
|
||||||
ubyte @zp x
|
ubyte @zp x
|
||||||
for x in 0 to len(cells)-1 {
|
for x in 0 to len(cells)-1 {
|
||||||
cells[x] = generate(x) ; next generation
|
cells[x] = generate(x) ; next generation
|
||||||
|
@ -1,11 +1,30 @@
|
|||||||
|
%import floats
|
||||||
|
%import textio
|
||||||
|
%option no_sysinit
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
label:
|
uword[4] words1 = [1,2,3,4]
|
||||||
str @shared name = "name"
|
uword[4] words2 = [99,88,77,66]
|
||||||
ubyte @shared bytevar
|
|
||||||
uword[] @shared array = [name, label, start, main, 9999]
|
for cx16.r0 in words1 {
|
||||||
uword[] @shared array2 = [&name, &label, &start, &main, 9999]
|
txt.print_uw(cx16.r0)
|
||||||
uword[] @shared array3 = [cx16.r0] ; error, is variables
|
txt.spc()
|
||||||
uword[] @shared array4 = [bytevar] ; error, is variables
|
}
|
||||||
|
txt.nl()
|
||||||
|
sys.memcopy(words2, words1, sizeof(words1))
|
||||||
|
for cx16.r0 in words1 {
|
||||||
|
txt.print_uw(cx16.r0)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
sys.memcopy([2222,3333,4444,5555], words1, sizeof(words1))
|
||||||
|
for cx16.r0 in words1 {
|
||||||
|
txt.print_uw(cx16.r0)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,5 @@ enum class IMSyscall(val number: Int) {
|
|||||||
CALLFAR(0x1017),
|
CALLFAR(0x1017),
|
||||||
CALLFAR2(0x1018),
|
CALLFAR2(0x1018),
|
||||||
MEMCOPY(0x1019),
|
MEMCOPY(0x1019),
|
||||||
MEMCOPY_SMALL(0x101a),
|
MEMCOPY_SMALL(0x101a)
|
||||||
ARRAYCOPY_SPLITW_TO_NORMAL(0x101b),
|
|
||||||
ARRAYCOPY_NORMAL_TO_SPLITW(0x101c),
|
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,8 @@ SYSCALLS:
|
|||||||
37 = memset
|
37 = memset
|
||||||
38 = memsetw
|
38 = memsetw
|
||||||
39 = stringcopy
|
39 = stringcopy
|
||||||
40 = ARRAYCOPY_SPLITW_TO_NORMAL
|
40 = ...unused...
|
||||||
41 = ARRAYCOPY_NORMAL_TO_SPLITW
|
41 = ...unused...
|
||||||
42 = memcopy_small
|
42 = memcopy_small
|
||||||
43 = load
|
43 = load
|
||||||
44 = load_raw
|
44 = load_raw
|
||||||
@ -103,8 +103,8 @@ enum class Syscall {
|
|||||||
MEMSET,
|
MEMSET,
|
||||||
MEMSETW,
|
MEMSETW,
|
||||||
STRINGCOPY,
|
STRINGCOPY,
|
||||||
ARRAYCOPY_SPLITW_TO_NORMAL,
|
UNUSED_SYSCALL_1, // TODO fixup
|
||||||
ARRAYCOPY_NORMAL_TO_SPLITW,
|
UNUSED_SYSCALL_2, // TODO fixup
|
||||||
MEMCOPY_SMALL,
|
MEMCOPY_SMALL,
|
||||||
LOAD,
|
LOAD,
|
||||||
LOAD_RAW,
|
LOAD_RAW,
|
||||||
@ -444,29 +444,6 @@ object SysCalls {
|
|||||||
vm.memory.setString(target, string, true)
|
vm.memory.setString(target, string, true)
|
||||||
returnValue(callspec.returns.single(), string.length, vm)
|
returnValue(callspec.returns.single(), string.length, vm)
|
||||||
}
|
}
|
||||||
Syscall.ARRAYCOPY_SPLITW_TO_NORMAL -> {
|
|
||||||
val (fromLsbA, fromMsbA, targetA, bytecountA) = getArgValues(callspec.arguments, vm)
|
|
||||||
val fromLsb = (fromLsbA as UShort).toInt()
|
|
||||||
val fromMsb = (fromMsbA as UShort).toInt()
|
|
||||||
val target = (targetA as UShort).toInt()
|
|
||||||
val bytecount = (bytecountA as UByte).toInt()
|
|
||||||
for(offset in 0..<bytecount) {
|
|
||||||
vm.memory.setUB(target+offset*2, vm.memory.getUB(fromLsb+offset))
|
|
||||||
vm.memory.setUB(target+offset*2+1, vm.memory.getUB(fromMsb+offset))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Syscall.ARRAYCOPY_NORMAL_TO_SPLITW -> {
|
|
||||||
val (fromA, targetLsbA, targetMsbA, bytecountA) = getArgValues(callspec.arguments, vm)
|
|
||||||
val from = (fromA as UShort).toInt()
|
|
||||||
val targetLsb = (targetLsbA as UShort).toInt()
|
|
||||||
val targetMsb = (targetMsbA as UShort).toInt()
|
|
||||||
val bytecount = (bytecountA as UByte).toInt()
|
|
||||||
for(offset in 0..<bytecount) {
|
|
||||||
vm.memory.setUB(targetLsb+offset, vm.memory.getUB(from+offset*2))
|
|
||||||
vm.memory.setUB(targetMsb+offset, vm.memory.getUB(from+offset*2+1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Syscall.LOAD -> {
|
Syscall.LOAD -> {
|
||||||
val (filenameA, addrA) = getArgValues(callspec.arguments, vm)
|
val (filenameA, addrA) = getArgValues(callspec.arguments, vm)
|
||||||
val filename = vm.memory.getString((filenameA as UShort).toInt())
|
val filename = vm.memory.getString((filenameA as UShort).toInt())
|
||||||
@ -572,6 +549,9 @@ object SysCalls {
|
|||||||
}
|
}
|
||||||
return returnValue(callspec.returns.single(), 30*256 + 80, vm) // just return some defaults in this case 80*30
|
return returnValue(callspec.returns.single(), 30*256 + 80, vm) // just return some defaults in this case 80*30
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Syscall.UNUSED_SYSCALL_1 -> TODO("remove this")
|
||||||
|
Syscall.UNUSED_SYSCALL_2 -> TODO("remove this")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,8 +117,6 @@ class VmProgramLoader {
|
|||||||
IMSyscall.CALLFAR2.number -> throw IRParseException("vm doesn't support the callfar2() syscall")
|
IMSyscall.CALLFAR2.number -> throw IRParseException("vm doesn't support the callfar2() syscall")
|
||||||
IMSyscall.MEMCOPY.number -> Syscall.MEMCOPY
|
IMSyscall.MEMCOPY.number -> Syscall.MEMCOPY
|
||||||
IMSyscall.MEMCOPY_SMALL.number -> Syscall.MEMCOPY_SMALL
|
IMSyscall.MEMCOPY_SMALL.number -> Syscall.MEMCOPY_SMALL
|
||||||
IMSyscall.ARRAYCOPY_SPLITW_TO_NORMAL.number -> Syscall.ARRAYCOPY_SPLITW_TO_NORMAL
|
|
||||||
IMSyscall.ARRAYCOPY_NORMAL_TO_SPLITW.number -> Syscall.ARRAYCOPY_NORMAL_TO_SPLITW
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user