diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 98d4080c2..1bb1acba1 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -19,26 +19,41 @@ sub start() { float fl2 = 2.2 memory byte mbyte = $c000 + memory byte mbyte2 = $d000 memory ubyte mubyte = $c001 + memory ubyte mubyte2 = $d001 memory word mword = $c002 + memory word mword2 = $d002 memory uword muword = $c004 + memory uword muword2 = $d004 memory float mfloat = $c006 + memory float mfloat2 = $d006 +; b = 1 +; derp = 1 +; w = 1 +; uw = 1 +; fl1 = 2.345 +; +; b = b2 +; derp = pixely +; w = w2 +; uw = uw2 +; fl1 = fl2 +; +; b = mbyte +; derp = mubyte +; w = mword +; uw = muword +; fl1 = mfloat +; +; mbyte = 1 +; mubyte = 1 +; mword = 1 +; muword = 1 +; mfloat = 3.456 - uw2 = uw - w2 = w - b2 = b - derp=pixely - fl2 = fl1 - fl2++ - - mbyte = 99 - mubyte = 99 - mword = 99 ; @todo fix ast error literal value missing wordvalue - muword = 99 ; @todo fix ast error literal value missing wordvalue - mword = 999.w - muword = 999.w - mfloat = 1.23456 + %breakpoint mbyte = b mubyte = derp @@ -46,12 +61,13 @@ sub start() { muword = uw mfloat = fl2 - ; @todo fix deze assignments: - b = mbyte - derp = mubyte - w = mword - uw = muword - fl2 = mfloat + %breakpoint + + mbyte = mbyte2 + mubyte = mubyte2 + mword = mword2 + muword = muword2 + mfloat = mfloat2 return diff --git a/compiler/src/prog8/compiler/intermediate/Instruction.kt b/compiler/src/prog8/compiler/intermediate/Instruction.kt index 3a1fb7492..269393c11 100644 --- a/compiler/src/prog8/compiler/intermediate/Instruction.kt +++ b/compiler/src/prog8/compiler/intermediate/Instruction.kt @@ -4,6 +4,7 @@ import prog8.stackvm.Syscall open class Instruction(val opcode: Opcode, val arg: Value? = null, + val arg2: Value? = null, val callLabel: String? = null, val callLabel2: String? = null) { @@ -24,6 +25,10 @@ open class Instruction(val opcode: Opcode, // opcodes that manipulate a variable "${opcode.toString().toLowerCase()} ${callLabel?:""} ${callLabel2?:""}".trimEnd() } + opcode in setOf(Opcode.COPY_MEM_BYTE, Opcode.COPY_MEM_WORD, Opcode.COPY_MEM_FLOAT) -> { + // opcodes with two (address) args + "${opcode.toString().toLowerCase()} $arg $arg2" + } callLabel==null -> "${opcode.toString().toLowerCase()} $argStr" else -> "${opcode.toString().toLowerCase()} $callLabel $argStr" } @@ -33,7 +38,7 @@ open class Instruction(val opcode: Opcode, } } -class LabelInstr(val name: String) : Instruction(opcode = Opcode.NOP) { +class LabelInstr(val name: String) : Instruction(Opcode.NOP, null, null) { override fun toString(): String { return "\n$name:" } diff --git a/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt index 26566c1dc..5471449a1 100644 --- a/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt +++ b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt @@ -80,7 +80,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap Opcode.PUSH_VAR_BYTE -> if (it[1].value.opcode == Opcode.POP_VAR_BYTE) { if (it[0].value.callLabel != it[1].value.callLabel) - instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_BYTE, null, it[0].value.callLabel, it[1].value.callLabel) + instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_BYTE, null, null, it[0].value.callLabel, it[1].value.callLabel) else instructionsToReplace[it[0].index] = Instruction(Opcode.NOP) instructionsToReplace[it[1].index] = Instruction(Opcode.NOP) @@ -88,7 +88,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap Opcode.PUSH_VAR_WORD -> if (it[1].value.opcode == Opcode.POP_VAR_WORD) { if (it[0].value.callLabel != it[1].value.callLabel) - instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_WORD, null, it[0].value.callLabel, it[1].value.callLabel) + instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_WORD, null, null, it[0].value.callLabel, it[1].value.callLabel) else instructionsToReplace[it[0].index] = Instruction(Opcode.NOP) instructionsToReplace[it[1].index] = Instruction(Opcode.NOP) @@ -96,7 +96,31 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap Opcode.PUSH_VAR_FLOAT -> if (it[1].value.opcode == Opcode.POP_VAR_FLOAT) { if (it[0].value.callLabel != it[1].value.callLabel) - instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_FLOAT, null, it[0].value.callLabel, it[1].value.callLabel) + instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_FLOAT, null, null, it[0].value.callLabel, it[1].value.callLabel) + else + instructionsToReplace[it[0].index] = Instruction(Opcode.NOP) + instructionsToReplace[it[1].index] = Instruction(Opcode.NOP) + } + Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> + if(it[1].value.opcode == Opcode.POP_MEM_B || it[1].value.opcode == Opcode.POP_MEM_UB) { + if(it[0].value.arg != it[1].value.arg) + instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_MEM_BYTE, it[0].value.arg, it[1].value.arg) + else + instructionsToReplace[it[0].index] = Instruction(Opcode.NOP) + instructionsToReplace[it[1].index] = Instruction(Opcode.NOP) + } + Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> + if(it[1].value.opcode == Opcode.POP_MEM_W || it[1].value.opcode == Opcode.POP_MEM_UW) { + if(it[0].value.arg != it[1].value.arg) + instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_MEM_WORD, it[0].value.arg, it[1].value.arg) + else + instructionsToReplace[it[0].index] = Instruction(Opcode.NOP) + instructionsToReplace[it[1].index] = Instruction(Opcode.NOP) + } + Opcode.PUSH_MEM_FLOAT -> + if(it[1].value.opcode == Opcode.POP_MEM_FLOAT) { + if(it[0].value.arg != it[1].value.arg) + instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_MEM_FLOAT, it[0].value.arg, it[1].value.arg) else instructionsToReplace[it[0].index] = Instruction(Opcode.NOP) instructionsToReplace[it[1].index] = Instruction(Opcode.NOP) @@ -279,7 +303,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap } fun instr(opcode: Opcode, arg: Value? = null, callLabel: String? = null) { - currentBlock.instructions.add(Instruction(opcode, arg, callLabel)) + currentBlock.instructions.add(Instruction(opcode, arg, callLabel = callLabel)) } fun label(labelname: String) { diff --git a/compiler/src/prog8/compiler/intermediate/Opcode.kt b/compiler/src/prog8/compiler/intermediate/Opcode.kt index e9f715fcf..638895a35 100644 --- a/compiler/src/prog8/compiler/intermediate/Opcode.kt +++ b/compiler/src/prog8/compiler/intermediate/Opcode.kt @@ -32,6 +32,9 @@ enum class Opcode { COPY_VAR_BYTE, COPY_VAR_WORD, COPY_VAR_FLOAT, + COPY_MEM_BYTE, + COPY_MEM_WORD, + COPY_MEM_FLOAT, // numeric arithmetic ADD_UB, diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 99f96b33d..2649aadb0 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -38,9 +38,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, when { it is LabelInstr -> LabelInstr(symname(it.name, block)) it.opcode == Opcode.INLINE_ASSEMBLY -> it - else -> Instruction(it.opcode, it.arg, - if (it.callLabel != null) symname(it.callLabel, block) else null, - if (it.callLabel2 != null) symname(it.callLabel2, block) else null) + else -> + Instruction(it.opcode, it.arg, it.arg2, + callLabel = if (it.callLabel != null) symname(it.callLabel, block) else null, + callLabel2 = if (it.callLabel2 != null) symname(it.callLabel2, block) else null) } }.toMutableList() val newConstants = block.integerConstants.map { symname(it.key, block) to it.value }.toMap().toMutableMap() @@ -318,7 +319,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, private fun instr2asm(ins: List): Int { // find best patterns (matching the most of the lines, then with the smallest weight) - val fragments = findPatterns(ins).sortedWith(compareBy({it.segmentSize}, {it.prio})) + val fragments = findPatterns(ins).sortedBy { it.segmentSize } if(fragments.isEmpty()) { // we didn't find any matching patterns (complex multi-instruction fragments), try simple ones val firstIns = ins[0] @@ -409,39 +410,39 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, // val floatConst = getFloatConst(ins.arg) // " lda #<$floatConst | ldy #>$floatConst | jsr prog8_lib.push_float" // } - Opcode.PUSH_VAR_BYTE -> { - when(ins.callLabel) { - "X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself") - "A" -> " sta ${ESTACK_LO.toHex()},x | dex" - "Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex" - else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex" - } - } - Opcode.PUSH_VAR_WORD -> { - when (ins.callLabel) { - "AX" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself") - "XY" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself") - "AY" -> " sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex" - else -> " lda ${ins.callLabel} | ldy ${ins.callLabel}+1 | sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex" - } - } - Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float" - Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> { - """ - lda ${ins.arg!!.integerValue().toHex()} - sta ${ESTACK_LO.toHex()},x - dex - """ - } - Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> { - """ - lda ${ins.arg!!.integerValue().toHex()} - sta ${ESTACK_LO.toHex()},x - lda ${(ins.arg.integerValue()+1).toHex()} - sta ${ESTACK_HI.toHex()},x - dex - """ - } +// Opcode.PUSH_VAR_BYTE -> { +// when(ins.callLabel) { +// "X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself") +// "A" -> " sta ${ESTACK_LO.toHex()},x | dex" +// "Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex" +// else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex" +// } +// } +// Opcode.PUSH_VAR_WORD -> { +// when (ins.callLabel) { +// "AX" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself") +// "XY" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself") +// "AY" -> " sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex" +// else -> " lda ${ins.callLabel} | ldy ${ins.callLabel}+1 | sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex" +// } +// } +// Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float" +// Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> { +// """ +// lda ${ins.arg!!.integerValue().toHex()} +// sta ${ESTACK_LO.toHex()},x +// dex +// """ +// } +// Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> { +// """ +// lda ${ins.arg!!.integerValue().toHex()} +// sta ${ESTACK_LO.toHex()},x +// lda ${(ins.arg.integerValue()+1).toHex()} +// sta ${ESTACK_HI.toHex()},x +// dex +// """ +// } Opcode.POP_MEM_B, Opcode.POP_MEM_UB -> { """ @@ -500,7 +501,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, return " st${ins.callLabel!!.toLowerCase()} ${ins.callLabel2}" else -> // var -> var - return " lda ${ins.callLabel}\n\tsta ${ins.callLabel2}" + return " lda ${ins.callLabel} | sta ${ins.callLabel2}" } } Opcode.COPY_VAR_WORD -> { @@ -556,6 +557,29 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, """ } + Opcode.COPY_MEM_BYTE -> " lda ${ins.arg!!.integerValue().toHex()} | sta ${ins.arg2!!.integerValue().toHex()}" + Opcode.COPY_MEM_WORD -> { + """ + lda ${ins.arg!!.integerValue().toHex()} + sta ${ins.arg2!!.integerValue().toHex()} + lda ${(ins.arg.integerValue()+1).toHex()} + sta ${(ins.arg2.integerValue()+1).toHex()} + """ + } + Opcode.COPY_MEM_FLOAT -> { + """ + lda #<${ins.arg!!.integerValue().toHex()} + ldy #>${ins.arg.integerValue().toHex()} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1+1} + lda #<${ins.arg2!!.integerValue().toHex()} + ldy #>${ins.arg2.integerValue().toHex()} + sta ${C64Zeropage.SCRATCH_W2} + sty ${C64Zeropage.SCRATCH_W2+1} + jsr prog8_lib.copy_float + """ + } + Opcode.INC_VAR_UB, Opcode.INC_VAR_B -> { when (ins.callLabel) { "A" -> " clc | adc #1" @@ -729,8 +753,17 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, // check for direct var assignments that should have been converted into COPY_VAR_XXX opcodes if((opcodes[0]==Opcode.PUSH_VAR_BYTE && opcodes[1]==Opcode.POP_VAR_BYTE) || (opcodes[0]==Opcode.PUSH_VAR_WORD && opcodes[1]==Opcode.POP_VAR_WORD) || - (opcodes[0]==Opcode.PUSH_VAR_FLOAT && opcodes[1]==Opcode.POP_VAR_FLOAT)) { - throw AssemblyError("push+pop var should have been changed into COPY_VAR_XXX opcode") + (opcodes[0]==Opcode.PUSH_VAR_FLOAT && opcodes[1]==Opcode.POP_VAR_FLOAT) || + (opcodes[0]==Opcode.PUSH_MEM_B && opcodes[1]==Opcode.POP_MEM_B) || + (opcodes[0]==Opcode.PUSH_MEM_B && opcodes[1]==Opcode.POP_MEM_UB) || + (opcodes[0]==Opcode.PUSH_MEM_UB && opcodes[1]==Opcode.POP_MEM_B) || + (opcodes[0]==Opcode.PUSH_MEM_UB && opcodes[1]==Opcode.POP_MEM_UB) || + (opcodes[0]==Opcode.PUSH_MEM_W && opcodes[1]==Opcode.POP_MEM_W) || + (opcodes[0]==Opcode.PUSH_MEM_W && opcodes[1]==Opcode.POP_MEM_UW) || + (opcodes[0]==Opcode.PUSH_MEM_UW && opcodes[1]==Opcode.POP_MEM_W) || + (opcodes[0]==Opcode.PUSH_MEM_UW && opcodes[1]==Opcode.POP_MEM_UW) || + (opcodes[0]==Opcode.PUSH_MEM_FLOAT && opcodes[1]==Opcode.POP_MEM_FLOAT)) { + throw AssemblyError("push+pop var/mem should have been changed into COPY_VAR_XXX opcode") } // check for operations that modify a single value, by putting it on the stack (and popping it afterwards) @@ -783,7 +816,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, if(pattern.sequence == opcodes.subList(0, pattern.sequence.size)) { val asm = pattern.asm(segment) if(asm!=null) - result.add(AsmFragment(asm, pattern.prio, pattern.sequence.size)) + result.add(AsmFragment(asm, pattern.sequence.size)) } } @@ -975,14 +1008,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } } - class AsmFragment(val asm: String, val prio: Int, var segmentSize: Int=0) + class AsmFragment(val asm: String, var segmentSize: Int=0) - class AsmPattern(val sequence: List, val prio: Int, val asm: (List)->String?) + class AsmPattern(val sequence: List, val asm: (List)->String?) private val patterns = listOf( // assignment: var = byte - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_VAR_BYTE), 10) { segment -> + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_VAR_BYTE)) { segment -> when (segment[1].callLabel) { "A", "X", "Y" -> " ld${segment[1].callLabel!!.toLowerCase()} #${segment[0].arg!!.integerValue().toHex()}" @@ -991,16 +1024,33 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } }, + // assignment: mem = bytevar/ubytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_B)) { segment -> + " lda ${segment[0].callLabel} | sta ${segment[1].arg!!.integerValue().toHex()}" + }, + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_UB)) { segment -> + " lda ${segment[0].callLabel} | sta ${segment[1].arg!!.integerValue().toHex()}" + }, + // assignment: mem = byte/ubyte - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_B), 10) { segment -> + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_B)) { segment -> " lda #${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].arg!!.integerValue().toHex()}" }, - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_UB), 9) { segment -> + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_UB)) { segment -> " lda #${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].arg!!.integerValue().toHex()}" }, + // assignment: (u)bytevar = membyte + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.POP_VAR_BYTE)) { segment -> + " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].callLabel}" + }, + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.POP_VAR_BYTE)) { segment -> + " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].callLabel}" + }, + + // assignment: var = word - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_VAR_WORD), 10) { segment -> + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_VAR_WORD)) { segment -> val number = segment[0].arg!!.integerValue().toHex() when (segment[1].callLabel) { "AX" -> " lda #<$number | ldx #>$number" @@ -1016,8 +1066,26 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } }, + // assignment: mem = wordvar/uwordvar + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_W)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${segment[1].arg!!.integerValue().toHex()} + lda ${segment[0].callLabel}+1 + sta ${(segment[1].arg!!.integerValue()+1).toHex()} + """ + }, + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_UW)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${segment[1].arg!!.integerValue().toHex()} + lda ${segment[0].callLabel}+1 + sta ${(segment[1].arg!!.integerValue()+1).toHex()} + """ + }, + // assignment: mem = word/uword - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_W), 10) { segment -> + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_W)) { segment -> """ lda #<${segment[0].arg!!.integerValue().toHex()} sta ${segment[1].arg!!.integerValue().toHex()} @@ -1025,7 +1093,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, sta ${(segment[1].arg!!.integerValue()+1).toHex()} """ }, - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_UW), 9) { segment -> + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_UW)) { segment -> """ lda #<${segment[0].arg!!.integerValue().toHex()} sta ${segment[1].arg!!.integerValue().toHex()} @@ -1034,8 +1102,26 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, """ }, + // assignment: (u)wordvar = memword + AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].arg!!.integerValue().toHex()} + sta ${segment[1].callLabel} + lda ${(segment[0].arg!!.integerValue()+1).toHex()} + sta ${segment[1].callLabel}+1 + """ + }, + AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].arg!!.integerValue().toHex()} + sta ${segment[1].callLabel} + lda ${(segment[0].arg!!.integerValue()+1).toHex()} + sta ${segment[1].callLabel}+1 + """ + }, + // assignment: var = float - AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_VAR_FLOAT), 10) { segment -> + AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> val floatConst = getFloatConst(segment[0].arg!!) """ lda #<$floatConst @@ -1050,8 +1136,23 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, """ }, + // assignment: var = memfloat + AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda #<${segment[0].arg!!.integerValue().toHex()} + ldy #>${segment[0].arg!!.integerValue().toHex()} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1+1} + lda #<${segment[1].callLabel} + ldy #>${segment[1].callLabel} + sta ${C64Zeropage.SCRATCH_W2} + sty ${C64Zeropage.SCRATCH_W2+1} + jsr prog8_lib.copy_float + """ + }, + // assignment: mem = float - AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_MEM_FLOAT), 10) { segment -> + AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> val floatConst = getFloatConst(segment[0].arg!!) """ lda #<$floatConst @@ -1067,7 +1168,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, }, // assignment: mem = floatvar - AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.POP_MEM_FLOAT), 10) { segment -> + AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> """ lda #<${segment[0].callLabel} ldy #>${segment[0].callLabel} @@ -1081,8 +1182,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, """ }, + // assignment: var = bytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE), 10) { segment -> + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> val index = segment[0].arg!!.integerValue() when (segment[2].callLabel) { "A", "X", "Y" -> diff --git a/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt b/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt index 83569b14b..275a5dc61 100644 --- a/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt +++ b/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt @@ -46,7 +46,7 @@ class AssemblyProgram(val name: String) { for(line in File(viceMonListFile).readLines()) { val match = pattern.matchEntire(line) if(match!=null) - breakpoints.add("break \$" + match.groupValues[0]) // todo check this + breakpoints.add("break \$" + match.groupValues[1]) } val num = breakpoints.size breakpoints.add(0, "; vice monitor breakpoint list now follows") diff --git a/compiler/src/prog8/optimizing/ConstantFolding.kt b/compiler/src/prog8/optimizing/ConstantFolding.kt index f263f368a..2a98c16f6 100644 --- a/compiler/src/prog8/optimizing/ConstantFolding.kt +++ b/compiler/src/prog8/optimizing/ConstantFolding.kt @@ -606,7 +606,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV DataType.WORD -> { // we can convert to WORD: any UBYTE/BYTE, UWORD <= 32767, FLOAT that's an integer -32768..32767 if(lv.type==DataType.UBYTE || lv.type==DataType.BYTE) - assignment.value = LiteralValue(DataType.WORD, lv.bytevalue!!, position=lv.position) + assignment.value = LiteralValue(DataType.WORD, wordvalue=lv.bytevalue!!.toInt(), position=lv.position) else if(lv.type==DataType.UWORD && lv.wordvalue!! <= 32767) assignment.value = LiteralValue(DataType.WORD, wordvalue=lv.wordvalue, position=lv.position) else if(lv.type==DataType.FLOAT) { diff --git a/compiler/src/prog8/stackvm/Program.kt b/compiler/src/prog8/stackvm/Program.kt index f4e121a1d..f042f1892 100644 --- a/compiler/src/prog8/stackvm/Program.kt +++ b/compiler/src/prog8/stackvm/Program.kt @@ -126,7 +126,13 @@ class Program (val name: String, Opcode.LINE -> Instruction(opcode, null, callLabel = args) Opcode.COPY_VAR_BYTE, Opcode.COPY_VAR_WORD, Opcode.COPY_VAR_FLOAT -> { val (v1, v2) = args!!.split(splitpattern, limit = 2) - Instruction(opcode, null, v1, v2) + Instruction(opcode, null, null, v1, v2) + } + Opcode.COPY_MEM_BYTE, Opcode.COPY_MEM_WORD, Opcode.COPY_MEM_FLOAT -> { + val (v1, v2) = args!!.split(splitpattern, limit = 2) + val address1 = getArgValue(v1, heap) + val address2 = getArgValue(v2, heap) + Instruction(opcode, address1, address2) } Opcode.JUMP, Opcode.CALL, Opcode.BNEG, Opcode.BPOS, Opcode.BZ, Opcode.BNZ, Opcode.BCS, Opcode.BCC -> { diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index bbee727dc..ff0443be4 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -812,6 +812,21 @@ class StackVm(private var traceOutputFile: String?) { checkDt(dest, DataType.FLOAT) variables[ins.callLabel2!!] = source } + Opcode.COPY_MEM_BYTE -> { + val sourceAddr = ins.arg!!.integerValue() + val destAddr = ins.arg2!!.integerValue() + mem.setUByte(destAddr, mem.getUByte(sourceAddr)) + } + Opcode.COPY_MEM_WORD -> { + val sourceAddr = ins.arg!!.integerValue() + val destAddr = ins.arg2!!.integerValue() + mem.setUWord(destAddr, mem.getUWord(sourceAddr)) + } + Opcode.COPY_MEM_FLOAT -> { + val sourceAddr = ins.arg!!.integerValue() + val destAddr = ins.arg2!!.integerValue() + mem.setFloat(destAddr, mem.getFloat(sourceAddr)) + } Opcode.POP_VAR_FLOAT -> { val value = evalstack.pop() checkDt(value, DataType.FLOAT) diff --git a/compiler/test/StackVMOpcodeTests.kt b/compiler/test/StackVMOpcodeTests.kt index 24a7edfef..5387774fe 100644 --- a/compiler/test/StackVMOpcodeTests.kt +++ b/compiler/test/StackVMOpcodeTests.kt @@ -282,10 +282,10 @@ class TestStackVmOpcodes { @Test fun testCopyVar() { val ins = mutableListOf( - Instruction(Opcode.COPY_VAR_BYTE, null, "bvar1", "bvar2"), - Instruction(Opcode.COPY_VAR_WORD, null, "wvar1", "wvar2"), - Instruction(Opcode.COPY_VAR_FLOAT, null, "fvar1", "fvar2"), - Instruction(Opcode.COPY_VAR_WORD, null, "wvar1", "bvar2")) + Instruction(Opcode.COPY_VAR_BYTE, null, null, "bvar1", "bvar2"), + Instruction(Opcode.COPY_VAR_WORD, null, null, "wvar1", "wvar2"), + Instruction(Opcode.COPY_VAR_FLOAT, null, null, "fvar1", "fvar2"), + Instruction(Opcode.COPY_VAR_WORD, null, null, "wvar1", "bvar2")) val vars = mapOf( "bvar1" to Value(DataType.UBYTE, 1), "bvar2" to Value(DataType.UBYTE, 2), @@ -305,6 +305,25 @@ class TestStackVmOpcodes { } } + @Test + fun testCopyMem() { + val ins = mutableListOf( + Instruction(Opcode.COPY_MEM_BYTE, Value(DataType.UWORD, 0xc000), Value(DataType.UWORD, 0xc001)), + Instruction(Opcode.COPY_MEM_WORD, Value(DataType.UWORD, 0xc100), Value(DataType.UWORD, 0xc102)), + Instruction(Opcode.COPY_MEM_FLOAT, Value(DataType.UWORD, 0xc200), Value(DataType.UWORD, 0xc300))) + val mem=mapOf(0xc000 to listOf(Value(DataType.UBYTE, 0x45)), + 0xc100 to listOf(Value(DataType.UWORD, 0xc2ca)), + 0xc200 to listOf(Value(DataType.FLOAT, 42.25))) + vm.load(makeProg(ins, mem=mem), null) + assertEquals(0, vm.mem.getUByte(0xc001)) + assertEquals(0, vm.mem.getUWord(0xc102)) + assertEquals(0.0, vm.mem.getFloat(0xc300)) + vm.step(3) + assertEquals(0x45, vm.mem.getUByte(0xc001)) + assertEquals(0xc2ca, vm.mem.getUWord(0xc102)) + assertEquals(42.25, vm.mem.getFloat(0xc300)) + } + @Test fun testAdd() { testBinaryOperator(Value(DataType.UBYTE, 140), Opcode.ADD_UB, Value(DataType.UBYTE, 222), Value(DataType.UBYTE, 106))