mirror of
https://github.com/irmen/prog8.git
synced 2024-05-29 01:41:32 +00:00
rest of the array copying
This commit is contained in:
parent
64c9c9b7fe
commit
d7f72056fc
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user