diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 44a8aac7f..4e14d1811 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -51,7 +51,7 @@ sub start() { ; all possible assignments to a BYTE VARIABLE (not array) -byte_assignment_to_register: +ubyte_assignment_to_register: A = 42 A = X A = ub2 @@ -237,83 +237,207 @@ ubyte_assignment_to_ubytearray: string[mubyte2] = mubyte2 string[mubyte2] = ubarr1[2] - ubarr2[mubyte2] = string[X] ;;todo via evaluation - ubarr2[mubyte2] = string[b] ;todo via evaluation - ubarr2[mubyte2] = string[ub] ;todo via evaluation - ubarr2[mubyte2] = string[mbyte2] ;todo via evaluation - ubarr2[mubyte2] = string[mubyte2] ;todo via evaluation - ubarr2[mubyte2] = ubarr1[X] ;todo via evaluation - ubarr2[mubyte2] = ubarr1[b] ;todo via evaluation - ubarr2[mubyte2] = ubarr1[ub] ;todo via evaluation - ubarr2[mubyte2] = ubarr1[mbyte2] ;todo via evaluation - ubarr2[mubyte2] = ubarr1[mubyte2] ;todo via evaluation - string[mubyte2] = ubarr1[Y] ;todo via evaluation - string[mubyte2] = ubarr1[b] ;todo via evaluation - string[mubyte2] = ubarr1[ub2] ;todo via evaluation - string[mubyte2] = ubarr1[mbyte2] ;todo via evaluation - string[mubyte2] = ubarr1[mubyte2] ;todo via evaluation - string[mubyte2] = string[mubyte2] ;todo via evaluation - - ubarr1[ubarr2[X]] = ubarr2[ubarr1[Y]] ; todo via evaluation-- check generated asm... +; ubarr2[mubyte2] = string[X] ;;todo via evaluation +; ubarr2[mubyte2] = string[b] ;todo via evaluation +; ubarr2[mubyte2] = string[ub] ;todo via evaluation +; ubarr2[mubyte2] = string[mbyte2] ;todo via evaluation +; ubarr2[mubyte2] = string[mubyte2] ;todo via evaluation +; ubarr2[mubyte2] = ubarr1[X] ;todo via evaluation +; ubarr2[mubyte2] = ubarr1[b] ;todo via evaluation +; ubarr2[mubyte2] = ubarr1[ub] ;todo via evaluation +; ubarr2[mubyte2] = ubarr1[mbyte2] ;todo via evaluation +; ubarr2[mubyte2] = ubarr1[mubyte2] ;todo via evaluation +; string[mubyte2] = ubarr1[Y] ;todo via evaluation +; string[mubyte2] = ubarr1[b] ;todo via evaluation +; string[mubyte2] = ubarr1[ub2] ;todo via evaluation +; string[mubyte2] = ubarr1[mbyte2] ;todo via evaluation +; string[mubyte2] = ubarr1[mubyte2] ;todo via evaluation +; string[mubyte2] = string[mubyte2] ;todo via evaluation +; +; ubarr1[ubarr2[X]] = ubarr2[ubarr1[Y]] ; todo via evaluation-- check generated asm... byte_assignment_to_bytearray: -; @todo + + barr2[3] = 42 + barr2[3] = b2 + barr2[3] = mbyte2 + barr2[3] = barr1[2] + barr2[3] = barr1[X] + barr2[3] = barr1[b] + barr2[3] = barr1[ub] + barr2[3] = barr1[mbyte2] + barr2[3] = barr1[mubyte2] + + barr2[Y] = 42 + barr2[Y] = b2 + barr2[Y] = mbyte2 + barr2[Y] = barr1[2] + barr2[Y] = barr1[X] + barr2[Y] = barr1[b] + barr2[Y] = barr1[ub] + barr2[Y] = barr1[mbyte2] + barr2[Y] = barr1[mubyte2] + + barr2[ub2] = 42 + barr2[ub2] = b2 + barr2[ub2] = mbyte2 + barr2[ub2] = barr1[2] + barr2[ub2] = barr1[X] + barr2[ub2] = barr1[b] + barr2[ub2] = barr1[ub] + barr2[ub2] = barr1[mbyte2] + barr2[ub2] = barr1[mubyte2] + + barr2[mubyte2] = 42 + barr2[mubyte2] = b2 + barr2[mubyte2] = mbyte2 + barr2[mubyte2] = barr1[2] + +; barr2[mubyte2] = string[X] ;;todo via evaluation +; barr2[mubyte2] = string[b] ;todo via evaluation +; barr2[mubyte2] = string[ub] ;todo via evaluation +; barr2[mubyte2] = string[mbyte2] ;todo via evaluation +; barr2[mubyte2] = string[mubyte2] ;todo via evaluation +; barr2[mubyte2] = ubarr1[X] ;todo via evaluation +; barr2[mubyte2] = ubarr1[b] ;todo via evaluation +; barr2[mubyte2] = ubarr1[ub] ;todo via evaluation +; barr2[mubyte2] = ubarr1[mbyte2] ;todo via evaluation +; barr2[mubyte2] = ubarr1[mubyte2] ;todo via evaluation +; +; barr1[ubarr2[X]] = barr2[ubarr1[Y]] ; todo via evaluation-- check generated asm... + + + + + +; all possible assignments to a UWORD VARIABLE (not array) + +uword_assignment_to_registerpair: + AY = 42 + AY = 42.w + AY = 42555 + AY = X + AY = XY + AY = ub2 + AY = mubyte2 + AY = string[4] + AY = ubarr1[2] + ;AY = uwarr1[X] ; todo via evaluation + ;AY = string[X] ; todo via evaluation + ;AY = string[b] ; todo via evaluation + ;AY = string[ub] ; todo via evaluation + ;AY = string[mbyte2] ; todo via evaluation + ;AY = string[mubyte2] ; todo via evaluation + ;AY = ubarr1[X] ; todo via evaluation + ;AY = ubarr1[b] ; todo via evaluation + ;AY = ubarr1[ub] ; todo via evaluation + ;AY = ubarr1[mbyte2] ; todo via evaluation + ;AY = ubarr1[mubyte2] ; todo via evaluation + ;AY = uwarr1[X] ; todo via evaluation + ;AY = uwarr1[b] ; todo via evaluation + ;AY = uwarr1[ub] ; todo via evaluation + ;AY = uwarr1[mbyte2] ; todo via evaluation + ;AY = uwarr1[mubyte2] ; todo via evaluation + + +uword_assignment_to_uwordvar: + uw = 42 + uw = 42.w + uw = 42555 + uw = X + uw = XY + uw = ub2 + uw = uw2 + uw = mubyte2 + uw = muword2 + uw = string[4] + uw = ubarr1[2] + uw = uwarr1[2] + ;uw = string[X] ; todo via evaluation + ;uw = string[b] ; todo via evaluation + ;uw = string[ub] ; todo via evaluation + ;uw = string[mbyte2] ; todo via evaluation + ;uw = string[mubyte2] ; todo via evaluation +; uw = ubarr1[X] ;; todo via evaluation +; uw = ubarr1[b] ;; todo via evaluation +; uw = ubarr1[ub] ; todo via evaluation +; uw = ubarr1[mbyte2] ; todo via evaluation +; uw = ubarr1[mubyte2] ; todo via evaluation +; uw = uwarr1[X] ; todo via evaluation +; uw = uwarr1[b] ; todo via evaluation +; uw = uwarr1[ub] ; todo via evaluation +; uw = uwarr1[mbyte2] ; todo via evaluation +; uw = uwarr1[mubyte2] ; todo via evaluation + + +uword_assignment_to_uwordmem: + muword = 42 + muword = 42.w + muword = 42555 + muword = X + muword = XY + muword = ub2 + muword = uw2 + muword = mubyte2 + muword = muword2 + muword = string[4] + muword = ubarr1[2] + muword = uwarr1[2] +; muword = string[X] ; todo via evaluation +; muword = string[b] ; todo via evaluation +; muword = string[ub] ; todo via evaluation +; muword = string[mbyte2] ; todo via evaluation +; muword = string[mubyte2] ; todo via evaluation +; muword = ubarr1[X] ; todo via evaluation +; muword = ubarr1[b] ; todo via evaluation +; muword = ubarr1[ub] ; todo via evaluation +; muword = ubarr1[mbyte2] ; todo via evaluation +; muword = ubarr1[mubyte2] ; todo via evaluation +; muword = uwarr1[X] ; todo via evaluation +; muword = uwarr1[b] ; todo via evaluation +; muword = uwarr1[ub] ; todo via evaluation +; muword = uwarr1[mbyte2] ; todo via evaluation +; muword = uwarr1[mubyte2] ; todo via evaluation + + + +word_assignment_to_wordvar: + w = -42 + w = -42.w + w = 12555 + w = X + w = ub2 + w = b2 + w = w2 + w = mubyte2 + w = mbyte2 + w = mword2 + w = string[4] + w = ubarr1[2] + w = barr1[2] + w = warr1[2] + ;uw = string[X] ; todo via evaluation + ;uw = string[b] ; todo via evaluation + ;uw = string[ub] ; todo via evaluation + ;uw = string[mbyte2] ; todo via evaluation + ;uw = string[mubyte2] ; todo via evaluation +; uw = ubarr1[X] ;; todo via evaluation +; uw = ubarr1[b] ;; todo via evaluation +; uw = ubarr1[ub] ; todo via evaluation +; uw = ubarr1[mbyte2] ; todo via evaluation +; uw = ubarr1[mubyte2] ; todo via evaluation +; uw = uwarr1[X] ; todo via evaluation +; uw = uwarr1[b] ; todo via evaluation +; uw = uwarr1[ub] ; todo via evaluation +; uw = uwarr1[mbyte2] ; todo via evaluation +; uw = uwarr1[mubyte2] ; todo via evaluation + -; all possible assignments to a WORD VARIABLE (not array) -; -;word_assignment_to_registerpair: -; AY = 42 -; AY = 42.w -; AY = 42555 -; AY = X -; AY = XY -; AY = ub -; AY = mubyte -; AY = ubarr1[2] -; AY = string[4] -; AY = uw -; AY = muword -; AY = uwarr1[2] -; AY = string[4] -; AY = XY[4] -; -;;word_assignment_to_wordvar: -; w = -42 -; w = -42.w -; w = -12345 -; w = X -; w = b2 -; w = ub2 -; w = w2 -; w = mbyte -; w = mubyte -; w = mword -; w = barr1[2] -; w = ubarr1[2] -; w = warr1[2] -; w = string[4] -; w = AY[4] -; -; uw = 42 -; uw = 42.w -; uw = 42555 -; uw = X -; uw = AY -; uw = ub2 -; uw = uw2 -; uw = mubyte -; uw = muword -; uw = ubarr1[2] -; uw = uwarr1[2] -; uw = string[4] -; uw = AY[4] -; -; ;; all possible assignments to a FLOAT VARIABLE ;float_assignment_to_floatvar: ; fl1 = 34 diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 8aad4911e..7c917e750 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -23,7 +23,7 @@ class AssemblyError(msg: String) : RuntimeException(msg) class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, val heap: HeapValues) { private val globalFloatConsts = mutableMapOf() - private lateinit var output: PrintWriter + private val assemblyLines = mutableListOf() private lateinit var block: IntermediateProgram.ProgramBlock private var breakpointCounter = 0 @@ -68,22 +68,47 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } } - private fun out(str: String?) = output.println(str) - fun compileToAssembly(): AssemblyProgram { println("\nGenerating assembly code from intermediate code... ") - // todo generate 6502 assembly - output = File("${program.name}.asm").printWriter() - output.use { - header() - for(b in program.blocks) - block2asm(b) + header() + for(b in program.blocks) + block2asm(b) + + optimizeAssembly(assemblyLines) + + File("${program.name}.asm").printWriter().use { + for (line in assemblyLines) { it.println(line) } } return AssemblyProgram(program.name) } + private fun optimizeAssembly(lines: MutableList) { + // sometimes, iny+dey / inx+dex / dey+iny / dex+inx sequences are generated, these can be eliminated. + val removeLines = mutableListOf() + for(pair in lines.withIndex().windowed(2)) { + val first = pair[0].value + val second = pair[1].value + if(first.trimStart().startsWith(';') || second.trimStart().startsWith(';')) + continue // skip over asm comments + + if((" iny" in first || "\tiny" in first) && (" dey" in second || "\tdey" in second) + || (" inx" in first || "\tinx" in first) && (" dex" in second || "\tdex" in second) + || (" dey" in first || "\tdey" in first) && (" iny" in second || "\tiny" in second) + || (" dex" in first || "\tdex" in first) && (" inx" in second || "\tinx" in second)) + { + removeLines.add(pair[0].index) + removeLines.add(pair[1].index) + } + } + + for(i in removeLines.reversed()) + lines.removeAt(i) + } + + private fun out(str: String) = assemblyLines.add(str) + private fun symname(scoped: String, block: IntermediateProgram.ProgramBlock): String { if(' ' in scoped) return scoped @@ -445,13 +470,13 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, // """ // } - Opcode.READ_INDEXED_VAR_BYTE -> { // @todo is this correct? - """ - ldy ${(ESTACK_LO+1).toHex()},x - lda ${ins.callLabel},y - sta ${(ESTACK_LO+1).toHex()},x - """ - } +// Opcode.READ_INDEXED_VAR_BYTE -> { // @todo is this correct? +// """ +// ldy ${(ESTACK_LO+1).toHex()},x +// lda ${ins.callLabel},y +// sta ${(ESTACK_LO+1).toHex()},x +// """ +// } Opcode.WRITE_INDEXED_VAR_BYTE -> { // @todo is this correct? """ @@ -925,9 +950,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } } - class AsmFragment(val asm: String, var segmentSize: Int=0) + private class AsmFragment(val asm: String, var segmentSize: Int=0) - class AsmPattern(val sequence: List, val altSequence: List?=null, val asm: (List)->String?) + private class AsmPattern(val sequence: List, val altSequence: List?=null, val asm: (List)->String?) private fun loadAFromIndexedByVar(idxVarInstr: Instruction, readArrayInstr: Instruction): String { // A = readArrayInstr [ idxVarInstr ] @@ -951,32 +976,33 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, private val patterns = listOf( // ----------- push value from array on the stack ------------- - // push: array[variable] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE)) { segment -> - val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) - " $loadByteA | sta ${ESTACK_LO.toHex()},x | dex" - }, - // push: array[mem index] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE)) { segment -> - """ - ldy ${segment[0].arg!!.integerValue().toHex()} - lda ${segment[1].callLabel},y - sta ${ESTACK_LO.toHex()},x - dex - """ - }, - // ----------- pop value off stack into array ------------- - // pop into: array[mem index] - AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - """ - ldy ${segment[0].arg!!.integerValue().toHex()} - inx - lda ${ESTACK_LO.toHex()},x - sta ${segment[1].callLabel},y - """ - }, +// // push: array[variable] +// AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE)) { segment -> +// val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) +// " $loadByteA | sta ${ESTACK_LO.toHex()},x | dex" +// }, +// // push: array[mem index] +// AsmPattern( +// listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE), +// listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE)) { segment -> +// """ +// ldy ${segment[0].arg!!.integerValue().toHex()} +// lda ${segment[1].callLabel},y +// sta ${ESTACK_LO.toHex()},x +// dex +// """ +// }, +// // ----------- pop value off stack into array ------------- +// // pop into: array[mem index] +// AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> +// """ +// ldy ${segment[0].arg!!.integerValue().toHex()} +// inx +// lda ${ESTACK_LO.toHex()},x +// sta ${segment[1].callLabel},y +// """ +// }, + // ----------- assignment to BYTE VARIABLE ---------------- // var = (u)bytevalue @@ -1257,206 +1283,229 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, """ } }, + // var = ubytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment -> + when(segment[0].callLabel) { + "A" -> when(segment[2].callLabel) { + "AX" -> " ldx #0" + "AY" -> " ldy #0" + "XY" -> " tax | ldy #0" + else -> " sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" + } + "X" -> when(segment[2].callLabel) { + "AX" -> " txa | ldx #0" + "AY" -> " txa | ldy #0" + "XY" -> " ldy #0" + else -> " stx ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" + } + "Y" -> when(segment[2].callLabel) { + "AX" -> " tya | ldx #0" + "AY" -> " tya | ldy #0" + "XY" -> " tya | tax | ldy #0" + else -> " sty ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" + } + else -> + when(segment[2].callLabel) { + "AX" -> " lda ${segment[0].callLabel} | ldx #0" + "AY" -> " lda ${segment[0].callLabel} | ldy #0" + "XY" -> " ldx ${segment[0].callLabel} | ldy #0" + else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" + } + } + }, + // var = other var + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> + when(segment[1].callLabel) { + "AX" -> + when(segment[0].callLabel) { + "AX" -> null + "AY" -> " stx ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1}" + "XY" -> " stx ${C64Zeropage.SCRATCH_B1} | tax | ldy ${C64Zeropage.SCRATCH_B1}" + else -> " lda ${segment[0].callLabel} | ldx ${segment[0].callLabel}+1" + } + "AY" -> + when(segment[0].callLabel) { + "AX" -> " sty ${C64Zeropage.SCRATCH_B1} | ldx ${C64Zeropage.SCRATCH_B1}" + "AY" -> null + "XY" -> " tax" + else -> " lda ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1" + } + "XY" -> + when(segment[0].callLabel) { + "AX" -> " txa | sty ${C64Zeropage.SCRATCH_B1} | ldx ${C64Zeropage.SCRATCH_B1}" + "AY" -> " txa" + "XY" -> null + else -> " ldx ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1" + } + else -> + when(segment[0].callLabel) { + "AX" -> " sta ${segment[1].callLabel} | stx ${segment[1].callLabel}+1" + "AY" -> " sta ${segment[1].callLabel} | sty ${segment[1].callLabel}+1" + "XY" -> " stx ${segment[1].callLabel} | sty ${segment[1].callLabel}+1" + else -> + """ + lda ${segment[0].callLabel} + ldy ${segment[0].callLabel}+1 + sta ${segment[1].callLabel} + sty ${segment[1].callLabel}+1 + """ + } + } + }, + // var = mem ubyte + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment -> + when(segment[2].callLabel) { + "AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx #0" + "AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy #0" + "XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy #0" + else -> " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" + } + }, + // var = mem (u)word + AsmPattern( + listOf(Opcode.PUSH_MEM_W, Opcode.POP_VAR_WORD), + listOf(Opcode.PUSH_MEM_UW, Opcode.POP_VAR_WORD)) { segment -> + when(segment[1].callLabel) { + "AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx ${(segment[0].arg!!.integerValue()+1).toHex()}" + "AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}" + "XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}" + else -> + """ + lda ${segment[0].arg!!.integerValue().toHex()} + sta ${segment[1].callLabel} + lda ${(segment[0].arg!!.integerValue()+1).toHex()} + sta ${segment[1].callLabel}+1 + """ + } + }, + // var = ubytearray[index_byte] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment -> + val index = segment[0].arg!!.integerValue().toHex() + when(segment[3].callLabel) { + "AX" -> " lda ${segment[1].callLabel}+$index | ldx #0" + "AY" -> " lda ${segment[1].callLabel}+$index | ldy #0" + "XY" -> " ldx ${segment[1].callLabel}+$index | ldy #0" + else -> " lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1" + } + }, + // var = (u)wordarray[index_byte] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> + val index = segment[0].arg!!.integerValue()*2 + when(segment[2].callLabel) { + "AX" -> " lda ${segment[1].callLabel}+$index | ldx ${segment[1].callLabel}+${index+1}" + "AY" -> " lda ${segment[1].callLabel}+$index | ldy ${segment[1].callLabel}+${index+1}" + "XY" -> " ldx ${segment[1].callLabel}+$index | ldy ${segment[1].callLabel}+${index+1}" + else -> " lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel} | lda ${segment[1].callLabel}+${index+1} | sta ${segment[2].callLabel}+1" + } + }, + // mem = (u)word value + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_WORD)) { segment -> + """ + lda #<${segment[0].arg!!.integerValue().toHex()} + sta ${segment[1].arg!!.integerValue().toHex()} + lda #>${segment[0].arg!!.integerValue().toHex()} + sta ${(segment[1].arg!!.integerValue()+1).toHex()} + """ + }, + // mem uword = ubyte var + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment -> + when(segment[0].callLabel) { + "A" -> " sta ${segment[2].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[2].arg!!.integerValue()+1).toHex()}" + "X" -> " stx ${segment[2].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[2].arg!!.integerValue()+1).toHex()}" + "Y" -> " sty ${segment[2].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[2].arg!!.integerValue()+1).toHex()}" + else -> " lda ${segment[0].callLabel} || sta ${segment[2].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[2].arg!!.integerValue()+1).toHex()}" + } + }, + // mem uword = mem ubyte + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${segment[0].arg!!.integerValue().toHex()} + sta ${segment[2].arg!!.integerValue().toHex()} + lda #0 + sta ${(segment[2].arg!!.integerValue()+1).toHex()} + """ + }, + // mem uword = uword var + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> + when(segment[0].callLabel) { + "AX" -> " sta ${segment[1].arg!!.integerValue().toHex()} | stx ${(segment[1].arg!!.integerValue()+1).toHex()}" + "AY" -> " sta ${segment[1].arg!!.integerValue().toHex()} | sty ${(segment[1].arg!!.integerValue()+1).toHex()}" + "XY" -> " stx ${segment[1].arg!!.integerValue().toHex()} | sty ${(segment[1].arg!!.integerValue()+1).toHex()}" + else -> " lda ${segment[0].callLabel} || sta ${segment[1].arg!!.integerValue().toHex()} | lda ${segment[0].callLabel}+1 | sta ${(segment[1].arg!!.integerValue()+1).toHex()}" + } + }, + // mem uword = mem uword + AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${segment[0].arg!!.integerValue().toHex()} + ldy ${(segment[0].arg!!.integerValue()+1).toHex()} + sta ${segment[1].arg!!.integerValue().toHex()} + sty ${(segment[1].arg!!.integerValue()+1).toHex()} + """ + }, + // mem uword = ubytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment -> + val index = segment[0].arg!!.integerValue() + when(segment[1].callLabel) { + "AX" -> " sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta ${segment[3].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[3].arg!!.integerValue()+1).toHex()}" + "AY" -> " sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta ${segment[3].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[3].arg!!.integerValue()+1).toHex()}" + "XY" -> " stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta ${segment[3].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[3].arg!!.integerValue()+1).toHex()}" + else -> + """ + lda ${segment[1].callLabel}+$index + ldy ${segment[1].callLabel}+${index+1} + sta ${segment[3].arg!!.integerValue().toHex()} + sty ${(segment[3].arg!!.integerValue()+1).toHex()} + """ + } + }, + // mem uword = (u)wordarray[indexvalue] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> + val index = segment[0].arg!!.integerValue()*2 + """ + lda ${segment[1].callLabel}+$index + ldy ${segment[1].callLabel}+1+$index + sta ${segment[2].arg!!.integerValue().toHex()} + sty ${(segment[2].arg!!.integerValue()+1).toHex()} + """ + }, + // word var = bytevar (sign extended) + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${segment[2].callLabel} + ora #$7f + bmi + + lda #0 ++ sta ${segment[2].callLabel}+1 + """ + }, + // var = membyte (sign extended) + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].arg!!.integerValue().toHex()} + sta ${segment[2].callLabel} + ora #$7f + bmi + + lda #0 ++ sta ${segment[2].callLabel}+1 + """ + }, + // var = bytearray[index_byte] (sign extended) + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment -> + val index = segment[0].arg!!.integerValue().toHex() + TODO("$segment (sign extended)") + }, + + + + -// // var = other var -// AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> -// when(segment[1].callLabel) { -// "AX" -> -// when(segment[0].callLabel) { -// "AX" -> null -// "AY" -> " stx ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1}" -// "XY" -> " stx ${C64Zeropage.SCRATCH_B1} | tax | ldy ${C64Zeropage.SCRATCH_B1}" -// else -> " lda ${segment[0].callLabel} | ldx ${segment[0].callLabel}+1" -// } -// "AY" -> -// when(segment[0].callLabel) { -// "AX" -> " sty ${C64Zeropage.SCRATCH_B1} | ldx ${C64Zeropage.SCRATCH_B1}" -// "AY" -> null -// "XY" -> " tax" -// else -> " lda ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1" -// } -// "XY" -> -// when(segment[0].callLabel) { -// "AX" -> " txa | sty ${C64Zeropage.SCRATCH_B1} | ldx ${C64Zeropage.SCRATCH_B1}" -// "AY" -> " txa" -// "XY" -> null -// else -> " ldx ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1" -// } -// else -> -// when(segment[0].callLabel) { -// "AX" -> " sta ${segment[1].callLabel} | stx ${segment[1].callLabel}+1" -// "AY" -> " sta ${segment[1].callLabel} | sty ${segment[1].callLabel}+1" -// "XY" -> " stx ${segment[1].callLabel} | sty ${segment[1].callLabel}+1" -// else -> -// """ -// lda ${segment[0].callLabel} -// ldy ${segment[0].callLabel}+1 -// sta ${segment[1].callLabel} -// sty ${segment[1].callLabel}+1 -// """ -// } -// } -// }, -// // var = mem (u)word -// AsmPattern( -// listOf(Opcode.PUSH_MEM_W, Opcode.POP_VAR_WORD), -// listOf(Opcode.PUSH_MEM_UW, Opcode.POP_VAR_WORD)) { segment -> -// when(segment[1].callLabel) { -// "AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx ${(segment[0].arg!!.integerValue()+1).toHex()}" -// "AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}" -// "XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}" -// else -> -// """ -// lda ${segment[0].arg!!.integerValue().toHex()} -// sta ${segment[1].callLabel} -// lda ${(segment[0].arg!!.integerValue()+1).toHex()} -// sta ${segment[1].callLabel}+1 -// """ -// } -// }, -// // var = ubytevar -// AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment -> -// when(segment[0].callLabel) { -// "A" -> when(segment[2].callLabel) { -// "AX" -> " ldx #0" -// "AY" -> " ldy #0" -// "XY" -> " tax | ldy #0" -// else -> " sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" -// } -// "X" -> when(segment[2].callLabel) { -// "AX" -> " txa | ldx #0" -// "AY" -> " txa | ldy #0" -// "XY" -> " ldy #0" -// else -> " stx ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" -// } -// "Y" -> when(segment[2].callLabel) { -// "AX" -> " tya | ldx #0" -// "AY" -> " tya | ldy #0" -// "XY" -> " tya | tax | ldy #0" -// else -> " sty ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" -// } -// else -> -// when(segment[2].callLabel) { -// "AX" -> " lda ${segment[0].callLabel} | ldx #0" -// "AY" -> " lda ${segment[0].callLabel} | ldy #0" -// "XY" -> " ldx ${segment[0].callLabel} | ldy #0" -// else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" -// } -// } -// }, -// // var = bytevar (sign extended) -// AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment -> -// """ -// lda ${segment[0].callLabel} -// sta ${segment[2].callLabel} -// ora #$7f -// bmi + -// lda #0 -//+ sta ${segment[2].callLabel}+1 -// """ -// }, -// // var = membyte (sign extended) -// AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment -> -// """ -// lda ${segment[0].arg!!.integerValue().toHex()} -// sta ${segment[2].callLabel} -// ora #$7f -// bmi + -// lda #0 -//+ sta ${segment[2].callLabel}+1 -// """ -// }, -// // var = mem ubyte -// AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment -> -// when(segment[2].callLabel) { -// "AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx #0" -// "AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy #0" -// "XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy #0" -// else -> " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" -// } -// }, -// // var = ubytearray[index_byte] -// AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment -> -// val index = segment[0].arg!!.integerValue().toHex() -// when(segment[3].callLabel) { -// "AX" -> " lda ${segment[1].callLabel}+$index | ldx #0" -// "AY" -> " lda ${segment[1].callLabel}+$index | ldy #0" -// "XY" -> " ldx ${segment[1].callLabel}+$index | ldy #0" -// else -> " lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1" -// } -// }, -// // var = bytearray[index_byte] (sign extended) -// AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment -> -// val index = segment[0].arg!!.integerValue().toHex() -// TODO("$segment (sign extended)") -// }, -// // var = (u)wordarray[index_byte] -// AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> -// val index = segment[0].arg!!.integerValue()*2 -// when(segment[2].callLabel) { -// "AX" -> " lda ${segment[1].callLabel}+$index | ldx ${segment[1].callLabel}+${index+1}" -// "AY" -> " lda ${segment[1].callLabel}+$index | ldy ${segment[1].callLabel}+${index+1}" -// "XY" -> " ldx ${segment[1].callLabel}+$index | ldy ${segment[1].callLabel}+${index+1}" -// else -> " lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel} | lda ${segment[1].callLabel}+${index+1} | sta ${segment[2].callLabel}+1" -// } -// }, // // var = bytearray[indexvar] (sign extended) VIA REGULAR STACK EVALUATION: Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD // // TODO: UB2UWORD + POP_VAR_WORD special pattern? // // var = (u)wordarray[indexvar] VIA REGULAR STACK EVALUATION: Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD -// -// -// // ----------- assignment to MEMORY WORD ---------------- -// // @todo mem=mem -// // mem = (u)word value -// AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_WORD)) { segment -> -// """ -// lda #<${segment[0].arg!!.integerValue().toHex()} -// sta ${segment[1].arg!!.integerValue().toHex()} -// lda #>${segment[0].arg!!.integerValue().toHex()} -// sta ${(segment[1].arg!!.integerValue()+1).toHex()} -// """ -// }, -// // mem = (u)word var -// AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> -// when(segment[0].callLabel) { -// "AX" -> " sta ${segment[1].arg!!.integerValue().toHex()} | stx ${(segment[1].arg!!.integerValue()+1).toHex()}" -// "AY" -> " sta ${segment[1].arg!!.integerValue().toHex()} | sty ${(segment[1].arg!!.integerValue()+1).toHex()}" -// "XY" -> " stx ${segment[1].arg!!.integerValue().toHex()} | sty ${(segment[1].arg!!.integerValue()+1).toHex()}" -// else -> -// """ -// lda ${segment[0].callLabel} -// sta ${segment[1].arg!!.integerValue().toHex()} -// lda ${segment[0].callLabel}+1 -// sta ${(segment[1].arg!!.integerValue()+1).toHex()} -// """ -// } -// }, -// // mem = (u)wordarray[indexvalue] -// AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> -// val index = segment[0].arg!!.integerValue()*2 -// """ -// lda ${segment[1].callLabel}+$index -// ldy ${segment[1].callLabel}+1+$index -// sta ${segment[2].arg!!.integerValue().toHex()} -// sty ${(segment[2].arg!!.integerValue()+1).toHex()} -// """ -// }, -// // assignment: mem uword = ubytearray[index_byte] -// AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_WORD)) { segment -> -// val index = segment[0].arg!!.integerValue() -// when(segment[1].callLabel) { -// "AX" -> " sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta ${segment[3].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[3].arg!!.integerValue()+1).toHex()}" -// "AY" -> " sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta ${segment[3].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[3].arg!!.integerValue()+1).toHex()}" -// "XY" -> " stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta ${segment[3].arg!!.integerValue().toHex()} | lda #0 | sta ${(segment[3].arg!!.integerValue()+1).toHex()}" -// else -> -// """ -// lda ${segment[1].callLabel}+$index -// ldy ${segment[1].callLabel}+${index+1} -// sta ${segment[3].arg!!.integerValue().toHex()} -// sty ${(segment[3].arg!!.integerValue()+1).toHex()} -// """ -// } -// }, + +