rest of the array copying

This commit is contained in:
Irmen de Jong 2024-02-10 03:07:49 +01:00
parent 64c9c9b7fe
commit d7f72056fc
13 changed files with 208 additions and 38 deletions

View File

@ -118,12 +118,38 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
jsr sys.memcopy""")
}
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)
TODO("split array to normal array copy $source -> $target")
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)
TODO("normal array to split array copy $source -> $target")
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

View File

@ -60,11 +60,11 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
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
val fromReg = codeGen.registers.nextFree()
val toReg = codeGen.registers.nextFree()
val countReg = 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=toReg, labelSymbol = target.name+"_lsb")
@ -75,23 +75,33 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=countReg, immediate = sourceLength)
it += codeGen.makeSyscall(IMSyscall.MEMCOPY, listOf(IRDataType.WORD to fromReg, IRDataType.WORD to toReg, IRDataType.WORD to countReg), returns = null)
}
return ExpressionCodeResult(result, IRDataType.BYTE, -1, -1)
}
else if(source.type in SplitWordArrayTypes) {
// split -> normal words
require(target.type==DataType.ARRAY_UW || target.type==DataType.ARRAY_W)
TODO("split array to normal array copy $source -> $target")
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)
TODO("normal array to split array copy $source -> $target")
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 fromReg = codeGen.registers.nextFree()
val toReg = codeGen.registers.nextFree()
val countReg = codeGen.registers.nextFree()
val eltsize = codeGen.options.compTarget.memorySize(source.type)
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=fromReg, labelSymbol = source.name)
@ -99,8 +109,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=countReg, immediate = sourceLength * eltsize)
}
result += codeGen.makeSyscall(IMSyscall.MEMCOPY, listOf(IRDataType.WORD to fromReg, IRDataType.WORD to toReg, IRDataType.WORD to countReg), returns = null)
return ExpressionCodeResult(result, IRDataType.BYTE, -1, -1)
}
return ExpressionCodeResult(result, IRDataType.BYTE, -1, -1)
}
private fun funcSquare(call: PtBuiltinFunctionCall, resultType: IRDataType): ExpressionCodeResult {

View File

@ -454,7 +454,7 @@ class StatementOptimizer(private val program: Program,
if(binExpr!=null) {
if(binExpr.operator in "+-") {
val value = binExpr.right.constValue(program)?.number?.toInt()
if(value!=null && value in 2..4) {
if(value!=null && value in 2..3) {
val stmts = mutableListOf<Statement>()
repeat(value) {
val incrdecr = Assignment(assignment.target.copy(),

View File

@ -330,3 +330,78 @@ containment_wordarray .proc
_found lda #1
rts
.pend
arraycopy_split_to_normal_words .proc
; P8ZP_SCRATCH_W1 = start of lsb array
; P8ZP_SCRATCH_W2 = start of msb array
; AY = start of normal word target array
; X = number of elements to copy
sta _modlsb+1
sty _modlsb+2
clc
adc #1
bne +
iny
+ sta _modmsb+1
sty _modmsb+2
ldy #0
- lda (P8ZP_SCRATCH_W1),y
_modlsb sta $ffff ; modified lsb store
lda _modlsb+1
clc
adc #2
sta _modlsb+1
bcc +
inc _modlsb+2
+ lda (P8ZP_SCRATCH_W2),y
_modmsb sta $ffff ; modified msb store
lda _modmsb+1
clc
adc #2
sta _modmsb+1
bcc +
inc _modmsb+2
+ iny
dex
bne -
rts
.pend
arraycopy_normal_to_split_words .proc
; P8ZP_SCRATCH_W1 = start of target lsb array
; P8ZP_SCRATCH_W2 = start of target msb array
; AY = start of normal word source array
; X = number of elements to copy
sta _modsrclsb+1
sty _modsrclsb+2
clc
adc #1
bne +
iny
+ sta _modsrcmsb+1
sty _modsrcmsb+2
ldy #0
_modsrclsb lda $ffff ; modified lsb read
sta (P8ZP_SCRATCH_W1),y
lda _modsrclsb+1
clc
adc #2
sta _modsrclsb+1
bcc +
inc _modsrclsb+2
+
_modsrcmsb lda $ffff ; modnfied msb read
sta (P8ZP_SCRATCH_W2),y
lda _modsrcmsb+1
clc
adc #2
sta _modsrcmsb+1
bcc +
inc _modsrcmsb+2
+ iny
dex
bne _modsrclsb
rts
.pend

View File

@ -400,10 +400,10 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
errors.report()
program.constantFold(errors, compilerOptions)
errors.report()
program.desugaring(errors)
errors.report()
program.reorderStatements(errors)
errors.report()
program.desugaring(errors)
errors.report()
program.changeNotExpressionAndIfComparisonExpr(errors, compilerOptions.compTarget)
errors.report()
program.addTypecasts(errors, compilerOptions)

View File

@ -35,8 +35,8 @@ internal class CodeDesugarer(val program: Program, private val errors: IErrorRep
val copy = FunctionCallStatement(
IdentifierReference(listOf("prog8_lib_arraycopy"), assignment.position),
mutableListOf(
IdentifierReference(listOf(sourceArray.name), assignment.position),
IdentifierReference(listOf(targetArray.name), assignment.position)
IdentifierReference(sourceArray.scopedName, assignment.position),
IdentifierReference(targetArray.scopedName, assignment.position)
), false, assignment.position)
return listOf(IAstModification.ReplaceNode(assignment, copy, parent))
}

View File

@ -143,16 +143,19 @@ main {
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
}
xtest("split array assignments") {
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

View File

@ -39,14 +39,16 @@ class TestVariables: FunSpec({
compileText(C64Target(), true, text, writeAssembly = true) shouldNotBe null
}
xtest("array initialization with array var assignment") {
test("array initialization with array var assignment") {
val text = """
main {
sub start() {
ubyte[3] @shared arrayvar = main.values
ubyte[3] @shared arrayvar=main.values1
arrayvar = main.values2
}
ubyte[] values = [1,2,3]
ubyte[] values1 = [1,2,3]
ubyte[] values2 = [1,2,3]
}
"""
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null

View File

@ -1,9 +1,12 @@
TODO
====
fix TODO's to assign from and to split arrays (BuiltinFuncGen + BuiltinFunctionAsmGen) -- cannot use simple single memcopy here (6502 + IR)
add an option to dump what variables ended up where (zp, normal ram, etc)
chess is larger than on 10.1 (other variables ended up in zeropage)
rockrunner is larger than on 10.1
medemo is quite a bit larger than on 10.1
assembler, imageviewer is bigger than before (since commit "added string.lstripped() and string.ltrimmed()" )
vm/pixelshader is larger than on 10.1
(after merge in boolean): move all "OperatorXinplace" from expressionGen to AssignmentGen, see if we can get rid of the Result return type.

View File

@ -5,7 +5,25 @@
%option no_sysinit
main {
sub start() {
screen.text_colors = [6,5,4,3,2,1]
for cx16.r0L in screen.text_colors {
txt.print_ub(cx16.r0L)
txt.spc()
}
txt.nl()
}
}
screen {
ubyte[6] text_colors
}
/*main222 {
sub start() {
str name1 = "name1"
str name2 = "name2"
uword[] @split names = [name1, name2, "name3"]
@ -18,18 +36,20 @@ main {
}
txt.nl()
; for cx16.r0 in addresses {
; txt.print_uw(cx16.r0)
; txt.spc()
; }
; txt.nl()
;
; addresses = names
;
; for cx16.r0 in addresses {
; txt.print_uw(cx16.r0)
; txt.spc()
; }
; txt.nl()
addresses = names
for cx16.r0 in addresses {
txt.print_uw(cx16.r0)
txt.spc()
}
txt.nl()
names = [9999,8888,7777]
names = addresses
for cx16.r0 in names {
txt.print_uw(cx16.r0)
txt.spc()
}
txt.nl()
}
}
}*/

View File

@ -30,4 +30,6 @@ enum class IMSyscall(val number: Int) {
CLAMP_FLOAT(0x1016),
CALLFAR(0x1017),
MEMCOPY(0x1018),
ARRAYCOPY_SPLITW_TO_NORMAL(0x1019),
ARRAYCOPY_NORMAL_TO_SPLITW(0x101a),
}

View File

@ -60,6 +60,8 @@ SYSCALLS:
50 = memset
51 = memsetw
52 = stringcopy
53 = ARRAYCOPY_SPLITW_TO_NORMAL
54 = ARRAYCOPY_NORMAL_TO_SPLITW
*/
enum class Syscall {
@ -116,6 +118,8 @@ enum class Syscall {
MEMSET,
MEMSETW,
STRINGCOPY,
ARRAYCOPY_SPLITW_TO_NORMAL,
ARRAYCOPY_NORMAL_TO_SPLITW,
;
companion object {
@ -575,6 +579,28 @@ object SysCalls {
vm.memory.setString(target, string, true)
returnValue(callspec.returns!!, 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))
}
}
}
}
}

View File

@ -127,6 +127,8 @@ class VmProgramLoader {
IMSyscall.CLAMP_FLOAT.number -> Syscall.CLAMP_FLOAT
IMSyscall.CALLFAR.number -> throw IRParseException("vm doesn't support the callfar() syscall")
IMSyscall.MEMCOPY.number -> Syscall.MEMCOPY
IMSyscall.ARRAYCOPY_SPLITW_TO_NORMAL.number -> Syscall.ARRAYCOPY_SPLITW_TO_NORMAL
IMSyscall.ARRAYCOPY_NORMAL_TO_SPLITW.number -> Syscall.ARRAYCOPY_NORMAL_TO_SPLITW
else -> null
}