From cc452dffb8266c716fbca52c056585dd66783ec4 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 9 Jul 2019 05:23:14 +0200 Subject: [PATCH] restructure asmgen to improve compilation and IDE performance issues --- .../src/prog8/compiler/target/c64/AsmGen.kt | 2852 +---------------- .../prog8/compiler/target/c64/AsmPatterns.kt | 2294 +++++++++++++ .../prog8/compiler/target/c64/SimpleAsm.kt | 531 +++ 3 files changed, 2844 insertions(+), 2833 deletions(-) create mode 100644 compiler/src/prog8/compiler/target/c64/AsmPatterns.kt create mode 100644 compiler/src/prog8/compiler/target/c64/SimpleAsm.kt diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 5ff3a164d..6d86d9fca 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -6,12 +6,9 @@ package prog8.compiler.target.c64 import prog8.ast.antlr.escape import prog8.ast.base.DataType import prog8.ast.base.initvarsSubName -import prog8.ast.base.printWarning import prog8.vm.RuntimeValue import prog8.compiler.* import prog8.compiler.intermediate.* -import prog8.vm.stackvm.Syscall -import prog8.vm.stackvm.syscallsForStackVm import java.io.File import java.util.* import kotlin.math.abs @@ -20,12 +17,28 @@ import kotlin.math.abs class AssemblyError(msg: String) : RuntimeException(msg) + +internal fun intVal(valueInstr: Instruction) = valueInstr.arg!!.integerValue() +internal fun hexVal(valueInstr: Instruction) = valueInstr.arg!!.integerValue().toHex() +internal fun hexValPlusOne(valueInstr: Instruction) = (valueInstr.arg!!.integerValue()+1).toHex() +internal fun getFloatConst(value: RuntimeValue): String = + globalFloatConsts[value.numericValue().toDouble()] + ?: throw AssemblyError("should have a global float const for number $value") + +internal val globalFloatConsts = mutableMapOf() + +internal fun signExtendA(into: String) = + """ + ora #$7f + bmi + + lda #0 ++ sta $into + """ + class AsmGen(private val options: CompilationOptions, private val program: IntermediateProgram, private val heap: HeapValues, private val zeropage: Zeropage) { - private val globalFloatConsts = mutableMapOf() private val assemblyLines = mutableListOf() private lateinit var block: IntermediateProgram.ProgramBlock - private var breakpointCounter = 0 init { // Convert invalid label names (such as "") to something that's allowed. @@ -399,7 +412,7 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter if(fragments.isEmpty()) { // we didn't find any matching patterns (complex multi-instruction fragments), try simple ones val firstIns = ins[0] - val singleAsm = simpleInstr2Asm(firstIns) + val singleAsm = simpleInstr2Asm(firstIns, block) if(singleAsm != null) { outputAsmFragment(singleAsm) return 1 @@ -422,556 +435,6 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter } } - private fun getFloatConst(value: RuntimeValue): String = - globalFloatConsts[value.numericValue().toDouble()] - ?: throw AssemblyError("should have a global float const for number $value") - - private fun simpleInstr2Asm(ins: Instruction): String? { - // a label 'instruction' is simply translated into a asm label - if(ins is LabelInstr) { - val labelresult = - if(ins.name.startsWith("${block.name}.")) - ins.name.substring(block.name.length+1) - else - ins.name - return if(ins.asmProc) labelresult+"\t\t.proc" else labelresult - } - - // simple opcodes that are translated directly into one or a few asm instructions - return when(ins.opcode) { - Opcode.LINE -> " ;\tsrc line: ${ins.callLabel}" - Opcode.NOP -> " nop" // shouldn't be present anymore though - Opcode.START_PROCDEF -> "" // is done as part of a label - Opcode.END_PROCDEF -> " .pend" - Opcode.TERMINATE -> " brk" - Opcode.SEC -> " sec" - Opcode.CLC -> " clc" - Opcode.SEI -> " sei" - Opcode.CLI -> " cli" - Opcode.CARRY_TO_A -> " lda #0 | adc #0" - Opcode.JUMP -> { - if(ins.callLabel!=null) - " jmp ${ins.callLabel}" - else - " jmp ${hexVal(ins)}" - } - Opcode.CALL -> { - if(ins.callLabel!=null) - " jsr ${ins.callLabel}" - else - " jsr ${hexVal(ins)}" - } - Opcode.RETURN -> " rts" - Opcode.RSAVE -> { - // save cpu status flag and all registers A, X, Y. - // see http://6502.org/tutorials/register_preservation.html - " php | sta ${C64Zeropage.SCRATCH_REG} | pha | txa | pha | tya | pha | lda ${C64Zeropage.SCRATCH_REG}" - } - Opcode.RRESTORE -> { - // restore all registers and cpu status flag - " pla | tay | pla | tax | pla | plp" - } - Opcode.RSAVEX -> " sta ${C64Zeropage.SCRATCH_REG} | txa | pha | lda ${C64Zeropage.SCRATCH_REG}" - Opcode.RRESTOREX -> " sta ${C64Zeropage.SCRATCH_REG} | pla | tax | lda ${C64Zeropage.SCRATCH_REG}" - Opcode.DISCARD_BYTE -> " inx" - Opcode.DISCARD_WORD -> " inx" - Opcode.DUP_B -> { - " dex | lda ${(ESTACK_LO+1).toHex()},x | sta ${ESTACK_LO.toHex()},x" - } - Opcode.DUP_W -> { - " dex | lda ${(ESTACK_LO+1).toHex()},x | sta ${ESTACK_LO.toHex()},x | lda ${(ESTACK_HI+1).toHex()},x | sta ${ESTACK_HI.toHex()},x " - } - Opcode.DISCARD_FLOAT -> " inx | inx | inx" - Opcode.INLINE_ASSEMBLY -> "@inline@" + (ins.callLabel2 ?: "") // All of the inline assembly is stored in the calllabel2 property. the '@inline@' is a special marker to accept it. - Opcode.INCLUDE_FILE -> { - val offset = if(ins.arg==null) "" else ", ${ins.arg.integerValue()}" - val length = if(ins.arg2==null) "" else ", ${ins.arg2.integerValue()}" - " .binary \"${ins.callLabel}\" $offset $length" - } - Opcode.SYSCALL -> { - if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr }) - throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}") - val call = Syscall.values().find { it.callNr==ins.arg.numericValue() } - when(call) { - Syscall.FUNC_SIN, - Syscall.FUNC_COS, - Syscall.FUNC_ABS, - Syscall.FUNC_TAN, - Syscall.FUNC_ATAN, - Syscall.FUNC_LN, - Syscall.FUNC_LOG2, - Syscall.FUNC_SQRT, - Syscall.FUNC_RAD, - Syscall.FUNC_DEG, - Syscall.FUNC_ROUND, - Syscall.FUNC_FLOOR, - Syscall.FUNC_CEIL, - Syscall.FUNC_RNDF, - Syscall.FUNC_ANY_F, - Syscall.FUNC_ALL_F, - Syscall.FUNC_MAX_F, - Syscall.FUNC_MIN_F, - Syscall.FUNC_SUM_F -> " jsr c64flt.${call.name.toLowerCase()}" - null -> "" - else -> " jsr prog8_lib.${call.name.toLowerCase()}" - } - } - Opcode.BREAKPOINT -> { - breakpointCounter++ - "_prog8_breakpoint_$breakpointCounter\tnop" - } - - Opcode.PUSH_BYTE -> { - " lda #${hexVal(ins)} | sta ${ESTACK_LO.toHex()},x | dex" - } - Opcode.PUSH_WORD -> { - val value = hexVal(ins) - " lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex" - } - Opcode.PUSH_FLOAT -> { - val floatConst = getFloatConst(ins.arg!!) - " lda #<$floatConst | ldy #>$floatConst | jsr c64flt.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. You should probably not use the X register (or only in trivial assignments)") - "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 -> { - " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda ${ins.callLabel}+1 | sta ${ESTACK_HI.toHex()},x | dex" - } - Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr c64flt.push_float" - Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> { - """ - lda ${hexVal(ins)} - sta ${ESTACK_LO.toHex()},x - dex - """ - } - Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> { - """ - lda ${hexVal(ins)} - sta ${ESTACK_LO.toHex()},x - lda ${hexValPlusOne(ins)} - sta ${ESTACK_HI.toHex()},x - dex - """ - } - Opcode.PUSH_MEM_FLOAT -> { - " lda #<${hexVal(ins)} | ldy #>${hexVal(ins)}| jsr c64flt.push_float" - } - Opcode.PUSH_MEMREAD -> { - """ - lda ${(ESTACK_LO+1).toHex()},x - sta (+) +1 - lda ${(ESTACK_HI+1).toHex()},x - sta (+) +2 -+ lda 65535 ; modified - sta ${(ESTACK_LO+1).toHex()},x - """ - } - - Opcode.PUSH_REGAY_WORD -> { - " sta ${ESTACK_LO.toHex()},x | tya | sta ${ESTACK_HI.toHex()},x | dex " - } - Opcode.PUSH_ADDR_HEAPVAR -> { - " lda #<${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda #>${ins.callLabel} | sta ${ESTACK_HI.toHex()},x | dex" - } - Opcode.POP_REGAX_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") - Opcode.POP_REGXY_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") - Opcode.POP_REGAY_WORD -> { - " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x " - } - - Opcode.READ_INDEXED_VAR_BYTE -> { - """ - ldy ${(ESTACK_LO+1).toHex()},x - lda ${ins.callLabel},y - sta ${(ESTACK_LO+1).toHex()},x - """ - } - Opcode.READ_INDEXED_VAR_WORD -> { - """ - lda ${(ESTACK_LO+1).toHex()},x - asl a - tay - lda ${ins.callLabel},y - sta ${(ESTACK_LO+1).toHex()},x - lda ${ins.callLabel}+1,y - sta ${(ESTACK_HI+1).toHex()},x - """ - } - Opcode.READ_INDEXED_VAR_FLOAT -> { - """ - lda #<${ins.callLabel} - ldy #>${ins.callLabel} - jsr c64flt.push_float_from_indexed_var - """ - } - Opcode.WRITE_INDEXED_VAR_BYTE -> { - """ - inx - ldy ${ESTACK_LO.toHex()},x - inx - lda ${ESTACK_LO.toHex()},x - sta ${ins.callLabel},y - """ - } - Opcode.WRITE_INDEXED_VAR_WORD -> { - """ - inx - lda ${ESTACK_LO.toHex()},x - asl a - tay - inx - lda ${ESTACK_LO.toHex()},x - sta ${ins.callLabel},y - lda ${ESTACK_HI.toHex()},x - sta ${ins.callLabel}+1,y - """ - } - Opcode.WRITE_INDEXED_VAR_FLOAT -> { - """ - lda #<${ins.callLabel} - ldy #>${ins.callLabel} - jsr c64flt.pop_float_to_indexed_var - """ - } - Opcode.POP_MEM_BYTE -> { - """ - inx - lda ${ESTACK_LO.toHex()},x - sta ${hexVal(ins)} - """ - } - Opcode.POP_MEM_WORD -> { - """ - inx - lda ${ESTACK_LO.toHex()},x - sta ${hexVal(ins)} - lda ${ESTACK_HI.toHex()},x - sta ${hexValPlusOne(ins)} - """ - } - Opcode.POP_MEM_FLOAT -> { - " lda ${hexVal(ins)} | ldy ${hexValPlusOne(ins)} | jsr c64flt.pop_float" - } - Opcode.POP_MEMWRITE -> { - """ - inx - lda ${ESTACK_LO.toHex()},x - sta (+) +1 - lda ${ESTACK_HI.toHex()},x - sta (+) +2 - inx - lda ${ESTACK_LO.toHex()},x -+ sta 65535 ; modified - """ - } - - Opcode.POP_VAR_BYTE -> { - when (ins.callLabel) { - "X" -> throw CompilerException("makes no sense to pop X, it's used as a stack pointer itself") - "A" -> " inx | lda ${ESTACK_LO.toHex()},x" - "Y" -> " inx | ldy ${ESTACK_LO.toHex()},x" - else -> " inx | lda ${ESTACK_LO.toHex()},x | sta ${ins.callLabel}" - } - } - Opcode.POP_VAR_WORD -> { - " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x | sta ${ins.callLabel} | sty ${ins.callLabel}+1" - } - Opcode.POP_VAR_FLOAT -> { - " lda #<${ins.callLabel} | ldy #>${ins.callLabel} | jsr c64flt.pop_float" - } - - Opcode.INC_VAR_UB, Opcode.INC_VAR_B -> { - when (ins.callLabel) { - "A" -> " clc | adc #1" - "X" -> " inx" - "Y" -> " iny" - else -> " inc ${ins.callLabel}" - } - } - Opcode.INC_VAR_UW, Opcode.INC_VAR_W -> { - " inc ${ins.callLabel} | bne + | inc ${ins.callLabel}+1 |+" - } - Opcode.INC_VAR_F -> { - """ - lda #<${ins.callLabel} - ldy #>${ins.callLabel} - jsr c64flt.inc_var_f - """ - } - Opcode.POP_INC_MEMORY -> { - """ - inx - lda ${ESTACK_LO.toHex()},x - sta (+) +1 - lda ${ESTACK_HI.toHex()},x - sta (+) +2 -+ inc 65535 ; modified - """ - } - Opcode.POP_DEC_MEMORY -> { - """ - inx - lda ${ESTACK_LO.toHex()},x - sta (+) +1 - lda ${ESTACK_HI.toHex()},x - sta (+) +2 -+ dec 65535 ; modified - """ - } - Opcode.DEC_VAR_UB, Opcode.DEC_VAR_B -> { - when (ins.callLabel) { - "A" -> " sec | sbc #1" - "X" -> " dex" - "Y" -> " dey" - else -> " dec ${ins.callLabel}" - } - } - Opcode.DEC_VAR_UW, Opcode.DEC_VAR_W -> { - " lda ${ins.callLabel} | bne + | dec ${ins.callLabel}+1 |+ | dec ${ins.callLabel}" - } - Opcode.DEC_VAR_F -> { - """ - lda #<${ins.callLabel} - ldy #>${ins.callLabel} - jsr c64flt.dec_var_f - """ - } - Opcode.INC_MEMORY -> " inc ${hexVal(ins)}" - Opcode.DEC_MEMORY -> " dec ${hexVal(ins)}" - Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> " inx | txa | pha | lda ${ESTACK_LO.toHex()},x | tax | inc ${ins.callLabel},x | pla | tax" - Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> " inx | txa | pha | lda ${ESTACK_LO.toHex()},x | tax | dec ${ins.callLabel},x | pla | tax" - - Opcode.NEG_B -> " jsr prog8_lib.neg_b" - Opcode.NEG_W -> " jsr prog8_lib.neg_w" - Opcode.NEG_F -> " jsr c64flt.neg_f" - Opcode.ABS_B -> " jsr prog8_lib.abs_b" - Opcode.ABS_W -> " jsr prog8_lib.abs_w" - Opcode.ABS_F -> " jsr c64flt.abs_f" - Opcode.POW_F -> " jsr c64flt.pow_f" - Opcode.INV_BYTE -> { - """ - lda ${(ESTACK_LO + 1).toHex()},x - eor #255 - sta ${(ESTACK_LO + 1).toHex()},x - """ - } - Opcode.INV_WORD -> " jsr prog8_lib.inv_word" - Opcode.NOT_BYTE -> " jsr prog8_lib.not_byte" - Opcode.NOT_WORD -> " jsr prog8_lib.not_word" - Opcode.BCS -> { - val label = ins.callLabel ?: hexVal(ins) - " bcs $label" - } - Opcode.BCC -> { - val label = ins.callLabel ?: hexVal(ins) - " bcc $label" - } - Opcode.BNEG -> { - val label = ins.callLabel ?: hexVal(ins) - " bmi $label" - } - Opcode.BPOS -> { - val label = ins.callLabel ?: hexVal(ins) - " bpl $label" - } - Opcode.BVC -> { - val label = ins.callLabel ?: hexVal(ins) - " bvc $label" - } - Opcode.BVS -> { - val label = ins.callLabel ?: hexVal(ins) - " bvs $label" - } - Opcode.BZ -> { - val label = ins.callLabel ?: hexVal(ins) - " beq $label" - } - Opcode.BNZ -> { - val label = ins.callLabel ?: hexVal(ins) - " bne $label" - } - Opcode.JZ -> { - val label = ins.callLabel ?: hexVal(ins) - """ - inx - lda ${(ESTACK_LO).toHex()},x - beq $label - """ - } - Opcode.JZW -> { - val label = ins.callLabel ?: hexVal(ins) - """ - inx - lda ${(ESTACK_LO).toHex()},x - beq $label - lda ${(ESTACK_HI).toHex()},x - beq $label - """ - } - Opcode.JNZ -> { - val label = ins.callLabel ?: hexVal(ins) - """ - inx - lda ${(ESTACK_LO).toHex()},x - bne $label - """ - } - Opcode.JNZW -> { - val label = ins.callLabel ?: hexVal(ins) - """ - inx - lda ${(ESTACK_LO).toHex()},x - bne $label - lda ${(ESTACK_HI).toHex()},x - bne $label - """ - } - Opcode.CAST_B_TO_UB -> "" // is a no-op, just carry on with the byte as-is - Opcode.CAST_UB_TO_B -> "" // is a no-op, just carry on with the byte as-is - Opcode.CAST_W_TO_UW -> "" // is a no-op, just carry on with the word as-is - Opcode.CAST_UW_TO_W -> "" // is a no-op, just carry on with the word as-is - Opcode.CAST_W_TO_UB -> "" // is a no-op, just carry on with the lsb of the word as-is - Opcode.CAST_W_TO_B -> "" // is a no-op, just carry on with the lsb of the word as-is - Opcode.CAST_UW_TO_UB -> "" // is a no-op, just carry on with the lsb of the uword as-is - Opcode.CAST_UW_TO_B -> "" // is a no-op, just carry on with the lsb of the uword as-is - Opcode.CAST_UB_TO_F -> " jsr c64flt.stack_ub2float" - Opcode.CAST_B_TO_F -> " jsr c64flt.stack_b2float" - Opcode.CAST_UW_TO_F -> " jsr c64flt.stack_uw2float" - Opcode.CAST_W_TO_F -> " jsr c64flt.stack_w2float" - Opcode.CAST_F_TO_UB -> " jsr c64flt.stack_float2uw" - Opcode.CAST_F_TO_B -> " jsr c64flt.stack_float2w" - Opcode.CAST_F_TO_UW -> " jsr c64flt.stack_float2uw" - Opcode.CAST_F_TO_W -> " jsr c64flt.stack_float2w" - Opcode.CAST_UB_TO_UW, Opcode.CAST_UB_TO_W -> " lda #0 | sta ${(ESTACK_HI+1).toHex()},x" // clear the msb - Opcode.CAST_B_TO_UW, Opcode.CAST_B_TO_W -> " lda ${(ESTACK_LO+1).toHex()},x | ${signExtendA("${(ESTACK_HI+1).toHex()},x")}" // sign extend the lsb - Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x" - Opcode.MKWORD -> " inx | lda ${ESTACK_LO.toHex()},x | sta ${(ESTACK_HI+1).toHex()},x " - - Opcode.ADD_UB, Opcode.ADD_B -> { // TODO inline better (pattern with more opcodes) - """ - lda ${(ESTACK_LO + 2).toHex()},x - clc - adc ${(ESTACK_LO + 1).toHex()},x - inx - sta ${(ESTACK_LO + 1).toHex()},x - """ - } - Opcode.SUB_UB, Opcode.SUB_B -> { // TODO inline better (pattern with more opcodes) - """ - lda ${(ESTACK_LO + 2).toHex()},x - sec - sbc ${(ESTACK_LO + 1).toHex()},x - inx - sta ${(ESTACK_LO + 1).toHex()},x - """ - } - Opcode.ADD_W, Opcode.ADD_UW -> " jsr prog8_lib.add_w" - Opcode.SUB_W, Opcode.SUB_UW -> " jsr prog8_lib.sub_w" - Opcode.MUL_B, Opcode.MUL_UB -> " jsr prog8_lib.mul_byte" - Opcode.MUL_W, Opcode.MUL_UW -> " jsr prog8_lib.mul_word" - Opcode.MUL_F -> " jsr c64flt.mul_f" - Opcode.ADD_F -> " jsr c64flt.add_f" - Opcode.SUB_F -> " jsr c64flt.sub_f" - Opcode.DIV_F -> " jsr c64flt.div_f" - Opcode.IDIV_UB -> " jsr prog8_lib.idiv_ub" - Opcode.IDIV_B -> " jsr prog8_lib.idiv_b" - Opcode.IDIV_W -> " jsr prog8_lib.idiv_w" - Opcode.IDIV_UW -> " jsr prog8_lib.idiv_uw" - - Opcode.AND_BYTE -> " jsr prog8_lib.and_b" - Opcode.OR_BYTE -> " jsr prog8_lib.or_b" - Opcode.XOR_BYTE -> " jsr prog8_lib.xor_b" - Opcode.AND_WORD -> " jsr prog8_lib.and_w" - Opcode.OR_WORD -> " jsr prog8_lib.or_w" - Opcode.XOR_WORD -> " jsr prog8_lib.xor_w" - - Opcode.BITAND_BYTE -> " jsr prog8_lib.bitand_b" - Opcode.BITOR_BYTE -> " jsr prog8_lib.bitor_b" - Opcode.BITXOR_BYTE -> " jsr prog8_lib.bitxor_b" - Opcode.BITAND_WORD -> " jsr prog8_lib.bitand_w" - Opcode.BITOR_WORD -> " jsr prog8_lib.bitor_w" - Opcode.BITXOR_WORD -> " jsr prog8_lib.bitxor_w" - - Opcode.REMAINDER_UB -> " jsr prog8_lib.remainder_ub" - Opcode.REMAINDER_UW -> " jsr prog8_lib.remainder_uw" - - Opcode.GREATER_B -> " jsr prog8_lib.greater_b" - Opcode.GREATER_UB -> " jsr prog8_lib.greater_ub" - Opcode.GREATER_W -> " jsr prog8_lib.greater_w" - Opcode.GREATER_UW -> " jsr prog8_lib.greater_uw" - Opcode.GREATER_F -> " jsr c64flt.greater_f" - - Opcode.GREATEREQ_B -> " jsr prog8_lib.greatereq_b" - Opcode.GREATEREQ_UB -> " jsr prog8_lib.greatereq_ub" - Opcode.GREATEREQ_W -> " jsr prog8_lib.greatereq_w" - Opcode.GREATEREQ_UW -> " jsr prog8_lib.greatereq_uw" - Opcode.GREATEREQ_F -> " jsr c64flt.greatereq_f" - - Opcode.EQUAL_BYTE -> " jsr prog8_lib.equal_b" - Opcode.EQUAL_WORD -> " jsr prog8_lib.equal_w" - Opcode.EQUAL_F -> " jsr c64flt.equal_f" - Opcode.NOTEQUAL_BYTE -> " jsr prog8_lib.notequal_b" - Opcode.NOTEQUAL_WORD -> " jsr prog8_lib.notequal_w" - Opcode.NOTEQUAL_F -> " jsr c64flt.notequal_f" - - Opcode.LESS_UB -> " jsr prog8_lib.less_ub" - Opcode.LESS_B -> " jsr prog8_lib.less_b" - Opcode.LESS_UW -> " jsr prog8_lib.less_uw" - Opcode.LESS_W -> " jsr prog8_lib.less_w" - Opcode.LESS_F -> " jsr c64flt.less_f" - - Opcode.LESSEQ_UB -> " jsr prog8_lib.lesseq_ub" - Opcode.LESSEQ_B -> " jsr prog8_lib.lesseq_b" - Opcode.LESSEQ_UW -> " jsr prog8_lib.lesseq_uw" - Opcode.LESSEQ_W -> " jsr prog8_lib.lesseq_w" - Opcode.LESSEQ_F -> " jsr c64flt.lesseq_f" - - Opcode.SHIFTEDL_BYTE -> " asl ${(ESTACK_LO+1).toHex()},x" - Opcode.SHIFTEDL_WORD -> " asl ${(ESTACK_LO+1).toHex()},x | rol ${(ESTACK_HI+1).toHex()},x" - Opcode.SHIFTEDR_SBYTE -> " lda ${(ESTACK_LO+1).toHex()},x | asl a | ror ${(ESTACK_LO+1).toHex()},x" - Opcode.SHIFTEDR_UBYTE -> " lsr ${(ESTACK_LO+1).toHex()},x" - Opcode.SHIFTEDR_SWORD -> " lda ${(ESTACK_HI+1).toHex()},x | asl a | ror ${(ESTACK_HI+1).toHex()},x | ror ${(ESTACK_LO+1).toHex()},x" - Opcode.SHIFTEDR_UWORD -> " lsr ${(ESTACK_HI+1).toHex()},x | ror ${(ESTACK_LO+1).toHex()},x" - - else -> null - } - } - - private fun optimizedIntMultiplicationsOnStack(mulIns: Instruction, amount: Int): String? { - - if(mulIns.opcode == Opcode.MUL_B || mulIns.opcode==Opcode.MUL_UB) { - if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) - printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount") - if(amount in setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40)) - return " jsr math.mul_byte_$amount" - if(mulIns.opcode == Opcode.MUL_B && amount in setOf(-3,-5,-6,-7,-9,-10,-11,-12,-13,-14,-15,-20,-25,-40)) - return " jsr prog8_lib.neg_b | jsr math.mul_byte_${-amount}" - } - else if(mulIns.opcode == Opcode.MUL_UW) { - if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) - printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount") - if(amount in setOf(3,5,6,7,9,10,12,15,20,25,40)) - return " jsr math.mul_word_$amount" - } - else if(mulIns.opcode == Opcode.MUL_W) { - if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) - printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount") - if(amount in setOf(3,5,6,7,9,10,12,15,20,25,40)) - return " jsr math.mul_word_$amount" - if(amount in setOf(-3,-5,-6,-7,-9,-10,-12,-15,-20,-25,-40)) - return " jsr prog8_lib.neg_w | jsr math.mul_word_${-amount}" - } - - return null - } - private fun findPatterns(segment: List): List { val opcodes = segment.map { it.opcode } val result = mutableListOf() @@ -1269,2281 +732,4 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter } private class AsmFragment(val asm: String, var segmentSize: Int=0) - - 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 ] - return when (idxVarInstr.callLabel) { - "A" -> " tay | lda ${readArrayInstr.callLabel},y" - "X" -> " txa | tay | lda ${readArrayInstr.callLabel},y" - "Y" -> " lda ${readArrayInstr.callLabel},y" - else -> " ldy ${idxVarInstr.callLabel} | lda ${readArrayInstr.callLabel},y" - } - } - - private fun loadAYFromWordIndexedByVar(idxVarInstr: Instruction, readArrayInstr: Instruction): String { - // AY = readWordArrayInstr [ idxVarInstr ] - return when(idxVarInstr.callLabel) { - "A" -> - """ - stx ${C64Zeropage.SCRATCH_B1} - asl a - tax - lda ${readArrayInstr.callLabel},x - ldy ${readArrayInstr.callLabel}+1,x - ldx ${C64Zeropage.SCRATCH_B1} - """ - "X" -> - """ - stx ${C64Zeropage.SCRATCH_B1} - txa - asl a - tax - lda ${readArrayInstr.callLabel},x - ldy ${readArrayInstr.callLabel}+1,x - ldx ${C64Zeropage.SCRATCH_B1} - """ - "Y" -> - """ - stx ${C64Zeropage.SCRATCH_B1} - tya - asl a - tax - lda ${readArrayInstr.callLabel},x - ldy ${readArrayInstr.callLabel}+1,x - ldx ${C64Zeropage.SCRATCH_B1} - """ - else -> - """ - stx ${C64Zeropage.SCRATCH_B1} - lda ${idxVarInstr.callLabel} - asl a - tax - lda ${readArrayInstr.callLabel},x - ldy ${readArrayInstr.callLabel}+1,x - ldx ${C64Zeropage.SCRATCH_B1} - """ - } - } - - private fun storeAToIndexedByVar(idxVarInstr: Instruction, writeArrayInstr: Instruction): String { - // writeArrayInstr [ idxVarInstr ] = A - return when (idxVarInstr.callLabel) { - "A" -> " tay | sta ${writeArrayInstr.callLabel},y" - "X" -> " stx ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1} | sta ${writeArrayInstr.callLabel},y" - "Y" -> " sta ${writeArrayInstr.callLabel},y" - else -> " ldy ${idxVarInstr.callLabel} | sta ${writeArrayInstr.callLabel},y" - } - } - - private fun intVal(valueInstr: Instruction) = valueInstr.arg!!.integerValue() - private fun hexVal(valueInstr: Instruction) = valueInstr.arg!!.integerValue().toHex() - private fun hexValPlusOne(valueInstr: Instruction) = (valueInstr.arg!!.integerValue()+1).toHex() - private fun signExtendA(into: String) = - """ - ora #$7f - bmi + - lda #0 -+ sta $into - """ - - private val patterns = listOf( - // ----------- assignment to BYTE VARIABLE ---------------- - // var = (u)bytevalue - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - when (segment[1].callLabel) { - "A", "X", "Y" -> - " ld${segment[1].callLabel!!.toLowerCase()} #${hexVal(segment[0])}" - else -> - " lda #${hexVal(segment[0])} | sta ${segment[1].callLabel}" - } - }, - // var = other var - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - when(segment[1].callLabel) { - "A" -> - when(segment[0].callLabel) { - "A" -> null - "X" -> " txa" - "Y" -> " tya" - else -> " lda ${segment[0].callLabel}" - } - "X" -> - when(segment[0].callLabel) { - "A" -> " tax" - "X" -> null - "Y" -> " tya | tax" - else -> " ldx ${segment[0].callLabel}" - } - "Y" -> - when(segment[0].callLabel) { - "A" -> " tay" - "X" -> " txa | tay" - "Y" -> null - else -> " ldy ${segment[0].callLabel}" - } - else -> - when(segment[0].callLabel) { - "A" -> " sta ${segment[1].callLabel}" - "X" -> " stx ${segment[1].callLabel}" - "Y" -> " sty ${segment[1].callLabel}" - else -> " lda ${segment[0].callLabel} | sta ${segment[1].callLabel}" - } - } - }, - // var = mem (u)byte - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.POP_VAR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.POP_VAR_BYTE)) { segment -> - when(segment[1].callLabel) { - "A", "X", "Y" -> " ld${segment[1].callLabel!!.toLowerCase()} ${hexVal(segment[0])}" - else -> " lda ${hexVal(segment[0])} | sta ${segment[1].callLabel}" - } - }, - // var = (u)bytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - val index = intVal(segment[0]) - when (segment[2].callLabel) { - "A", "X", "Y" -> - " ld${segment[2].callLabel!!.toLowerCase()} ${segment[1].callLabel}+$index" - else -> - " lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel}" - } - }, - // var = (u)bytearray[indexvar] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) - when(segment[2].callLabel) { - "A" -> " $loadByteA" - "X" -> " $loadByteA | tax" - "Y" -> " $loadByteA | tay" - else -> " $loadByteA | sta ${segment[2].callLabel}" - } - }, - // var = (u)bytearray[mem index var] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - val loadByteA = " ldy ${hexVal(segment[0])} | lda ${segment[1].callLabel},y" - when(segment[2].callLabel) { - "A" -> " $loadByteA" - "X" -> " $loadByteA | tax" - "Y" -> " $loadByteA | tay" - else -> " $loadByteA | sta ${segment[2].callLabel}" - } - }, - - - // ----------- assignment to BYTE MEMORY ---------------- - // mem = (u)byte value - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_BYTE)) { segment -> - " lda #${hexVal(segment[0])} | sta ${hexVal(segment[1])}" - }, - // mem = (u)bytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_BYTE)) { segment -> - when(segment[0].callLabel) { - "A" -> " sta ${hexVal(segment[1])}" - "X" -> " stx ${hexVal(segment[1])}" - "Y" -> " sty ${hexVal(segment[1])}" - else -> " lda ${segment[0].callLabel} | sta ${hexVal(segment[1])}" - } - }, - // mem = mem (u)byte - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.POP_MEM_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.POP_MEM_BYTE)) { segment -> - " lda ${hexVal(segment[0])} | sta ${hexVal(segment[1])}" - }, - // mem = (u)bytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_BYTE)) { segment -> - val address = hexVal(segment[2]) - val index = intVal(segment[0]) - " lda ${segment[1].callLabel}+$index | sta $address" - }, - // mem = (u)bytearray[indexvar] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_BYTE)) { segment-> - val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) - " $loadByteA | sta ${hexVal(segment[2])}" - }, - // mem = (u)bytearray[mem index var] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_BYTE)) { segment -> - """ - ldy ${hexVal(segment[0])} - lda ${segment[1].callLabel},y - sta ${hexVal(segment[2])} - """ - }, - - - // ----------- assignment to BYTE ARRAY ---------------- - // bytearray[index] = (u)byte value - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val index = intVal(segment[1]) - val value = hexVal(segment[0]) - " lda #$value | sta ${segment[2].callLabel}+$index" - }, - // bytearray[index] = (u)bytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val index = intVal(segment[1]) - when(segment[0].callLabel) { - "A" -> " sta ${segment[2].callLabel}+$index" - "X" -> " stx ${segment[2].callLabel}+$index" - "Y" -> " sty ${segment[2].callLabel}+$index" - else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}+$index" - } - }, - // bytearray[index] = mem(u)byte - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val index = intVal(segment[1]) - " lda ${hexVal(segment[0])} | sta ${segment[2].callLabel}+$index" - }, - - // bytearray[index var] = (u)byte value - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val storeA = storeAToIndexedByVar(segment[1], segment[2]) - " lda #${hexVal(segment[0])} | $storeA" - }, - // (u)bytearray[index var] = (u)bytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val storeA = storeAToIndexedByVar(segment[1], segment[2]) - when(segment[0].callLabel) { - "A" -> " $storeA" - "X" -> " txa | $storeA" - "Y" -> " tya | $storeA" - else -> " lda ${segment[0].callLabel} | $storeA" - } - }, - // (u)bytearray[index var] = mem (u)byte - AsmPattern( - listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE), - listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val storeA = storeAToIndexedByVar(segment[1], segment[2]) - " lda ${hexVal(segment[0])} | $storeA" - }, - - // bytearray[index mem] = (u)byte value - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - """ - lda #${hexVal(segment[0])} - ldy ${hexVal(segment[1])} - sta ${segment[2].callLabel},y - """ - }, - // bytearray[index mem] = (u)byte var - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val loadY = " ldy ${hexVal(segment[1])}" - when(segment[0].callLabel) { - "A" -> " $loadY | sta ${segment[2].callLabel},y" - "X" -> " txa | $loadY | sta ${segment[2].callLabel},y" - "Y" -> " tya | $loadY | sta ${segment[2].callLabel},y" - else -> " lda ${segment[0].callLabel} | $loadY | sta ${segment[2].callLabel},y" - } - }, - // bytearray[index mem] = mem(u)byte - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - """ - ldy ${hexVal(segment[1])} - lda ${hexVal(segment[0])} - sta ${segment[2].callLabel},y - """ - }, - - // (u)bytearray2[index2] = (u)bytearray1[index1] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment-> - val index1 = intVal(segment[0]) - val index2 = intVal(segment[2]) - " lda ${segment[1].callLabel}+$index1 | sta ${segment[3].callLabel}+$index2" - }, - // (u)bytearray2[index2] = (u)bytearray[indexvar] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) - val index2 = intVal(segment[2]) - " $loadByteA | sta ${segment[3].callLabel}+$index2" - }, - // (u)bytearray[index2] = (u)bytearray[mem ubyte] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val index2 = intVal(segment[2]) - """ - ldy ${hexVal(segment[0])} - lda ${segment[1].callLabel},y - sta ${segment[3].callLabel}+$index2 - """ - }, - - // (u)bytearray2[idxvar2] = (u)bytearray1[index1] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val storeA = storeAToIndexedByVar(segment[2], segment[3]) - val index1 = intVal(segment[0]) - " lda ${segment[1].callLabel}+$index1 | $storeA" - }, - // (u)bytearray2[idxvar2] = (u)bytearray1[idxvar] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val loadA = loadAFromIndexedByVar(segment[0], segment[1]) - val storeA = storeAToIndexedByVar(segment[2], segment[3]) - " $loadA | $storeA" - }, - // (u)bytearray2[idxvar2] = (u)bytearray1[mem ubyte] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val storeA = storeAToIndexedByVar(segment[2], segment[3]) - " ldy ${hexVal(segment[0])} | lda ${segment[1].callLabel},y | $storeA" - }, - - // (u)bytearray2[index mem] = (u)bytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val index1 = intVal(segment[0]) - """ - lda ${segment[1].callLabel}+$index1 - ldy ${hexVal(segment[2])} - sta ${segment[3].callLabel},y - """ - }, - - - - // ----------- assignment to WORD VARIABLE ---------------- - // var = wordvalue - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_VAR_WORD)) { segment -> - val number = hexVal(segment[0]) - """ - lda #<$number - ldy #>$number - sta ${segment[1].callLabel} - sty ${segment[1].callLabel}+1 - """ - }, - // var = ubytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> - when(segment[0].callLabel) { - "A" -> " sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" - "X" -> " stx ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" - "Y" -> " sty ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" - 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 -> - """ - lda ${segment[0].callLabel} - ldy ${segment[0].callLabel}+1 - sta ${segment[1].callLabel} - sty ${segment[1].callLabel}+1 - """ - }, - // var = address-of other var - AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_VAR_WORD)) { segment -> - """ - lda #<${segment[0].callLabel} - ldy #>${segment[0].callLabel} - sta ${segment[1].callLabel} - sty ${segment[1].callLabel}+1 - """ - }, - // var = mem ubyte - AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> - " lda ${hexVal(segment[0])} | 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 -> - """ - lda ${hexVal(segment[0])} - sta ${segment[1].callLabel} - lda ${hexValPlusOne(segment[0])} - sta ${segment[1].callLabel}+1 - """ - }, - // var = ubytearray[index_byte] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> - val index = hexVal(segment[0]) - " lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1" - }, - // var = ubytearray[index var] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> - val loadA = loadAFromIndexedByVar(segment[0], segment[1]) - " $loadA | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1" - }, - // var = ubytearray[index mem] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - 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 = intVal(segment[0])*2 - " lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel} | lda ${segment[1].callLabel}+${index+1} | sta ${segment[2].callLabel}+1" - }, - // var = (u)wordarray[index var] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> - val loadAY = loadAYFromWordIndexedByVar(segment[0], segment[1]) - """ - $loadAY - sta ${segment[2].callLabel} - sty ${segment[2].callLabel}+1 - """ - }, - // var = (u)wordarray[index mem] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - asl a - tay - lda ${segment[1].callLabel},y - sta ${segment[2].callLabel} - lda ${segment[1].callLabel}+1,y - sta ${segment[2].callLabel}+1 - """ - }, - // mem = (u)word value - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_WORD)) { segment -> - """ - lda #<${hexVal(segment[0])} - ldy #>${hexVal(segment[0])} - sta ${hexVal(segment[1])} - sty ${hexValPlusOne(segment[1])} - """ - }, - // mem uword = ubyte var - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> - when(segment[0].callLabel) { - "A" -> " sta ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}" - "X" -> " stx ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}" - "Y" -> " sty ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}" - else -> " lda ${segment[0].callLabel} || sta ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}" - } - }, - // mem uword = mem ubyte - AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${hexVal(segment[2])} - lda #0 - sta ${hexValPlusOne(segment[2])} - """ - }, - // mem uword = uword var - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> - " lda ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1 | sta ${hexVal(segment[1])} | sty ${hexValPlusOne(segment[1])}" - }, - // mem uword = address-of var - AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_MEM_WORD)) { segment -> - " lda #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} | sta ${hexVal(segment[1])} | sty ${hexValPlusOne(segment[1])}" - }, - // mem (u)word = mem (u)word - AsmPattern( - listOf(Opcode.PUSH_MEM_UW, Opcode.POP_MEM_WORD), - listOf(Opcode.PUSH_MEM_W, Opcode.POP_MEM_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - ldy ${hexValPlusOne(segment[0])} - sta ${hexVal(segment[1])} - sty ${hexValPlusOne(segment[1])} - """ - }, - // mem uword = ubytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> - val index = intVal(segment[0]) - """ - lda ${segment[1].callLabel}+$index - ldy #0 - sta ${hexVal(segment[3])} - sty ${hexValPlusOne(segment[3])} - """ - }, - // mem uword = bytearray[index] (sign extended) - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> - val index = intVal(segment[0]) - """ - lda ${segment[1].callLabel}+$index - sta ${hexVal(segment[3])} - ${signExtendA(hexValPlusOne(segment[3]))} - """ - }, - // mem uword = bytearray[index var] (sign extended) - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> - val loadA = loadAFromIndexedByVar(segment[0], segment[1]) - """ - $loadA - sta ${hexVal(segment[3])} - ${signExtendA(hexValPlusOne(segment[3]))} - """ - }, - // mem uword = bytearray[mem (u)byte] (sign extended) - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${hexVal(segment[3])} - ${signExtendA(hexValPlusOne(segment[3]))} - """ - }, - // mem uword = ubytearray[index var] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> - val loadA = loadAFromIndexedByVar(segment[0], segment[1]) - " $loadA | sta ${hexVal(segment[3])} | lda #0 | sta ${hexValPlusOne(segment[3])}" - }, - // mem uword = ubytearray[mem (u)bute] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${hexVal(segment[3])} - lda #0 - sta ${hexValPlusOne(segment[3])} - """ - }, - // mem uword = (u)wordarray[indexvalue] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> - val index = intVal(segment[0])*2 - """ - lda ${segment[1].callLabel}+$index - ldy ${segment[1].callLabel}+1+$index - sta ${hexVal(segment[2])} - sty ${hexValPlusOne(segment[2])} - """ - }, - // mem uword = (u)wordarray[index var] - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> - val loadAY = loadAYFromWordIndexedByVar(segment[0], segment[1]) - """ - $loadAY - sta ${hexVal(segment[2])} - sty ${hexValPlusOne(segment[2])} - """ - }, - // mem uword = (u)wordarray[mem index] - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - asl a - tay - lda ${segment[1].callLabel},y - sta ${hexVal(segment[2])} - lda ${segment[1].callLabel}+1,y - sta ${hexValPlusOne(segment[2])} - """ - }, - // word var = bytevar (sign extended) - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${segment[2].callLabel} - ${signExtendA(segment[2].callLabel + "+1")} - """ - }, - // mem word = bytevar (sign extended) - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${hexVal(segment[2])} - ${signExtendA(hexValPlusOne(segment[2]))} - """ - }, - // mem word = mem byte (sign extended) - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${hexVal(segment[2])} - ${signExtendA(hexValPlusOne(segment[2]))} - """ - }, - // var = membyte (sign extended) - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${segment[2].callLabel} - ${signExtendA(segment[2].callLabel + "+1")} - """ - }, - // var = bytearray[index_byte] (sign extended) - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> - val index = hexVal(segment[0]) - """ - lda ${segment[1].callLabel}+$index - sta ${segment[3].callLabel} - ${signExtendA(segment[3].callLabel + "+1")} - """ - }, - // var = bytearray[index var] (sign extended) - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> - val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) - """ - $loadByteA - sta ${segment[3].callLabel} - ${signExtendA(segment[3].callLabel + "+1")} - """ - }, - // var = bytearray[mem (u)byte] (sign extended) - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD), - listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${segment[3].callLabel} - ${signExtendA(segment[3].callLabel + "+1")} - """ - }, - - // ----------- assignment to UWORD ARRAY ---------------- - // uwordarray[index] = (u)word value - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[1])*2 - val value = hexVal(segment[0]) - """ - lda #<$value - ldy #>$value - sta ${segment[2].callLabel}+$index - sty ${segment[2].callLabel}+${index+1} - """ - }, - // uwordarray[index mem] = (u)word value - AsmPattern( - listOf(Opcode.PUSH_WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val value = hexVal(segment[0]) - """ - lda ${hexVal(segment[1])} - asl a - tay - lda #<$value - sta ${segment[2].callLabel},y - lda #>$value - sta ${segment[2].callLabel}+1,y - """ - }, - // uwordarray[index mem] = mem (u)word - AsmPattern( - listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[1])} - asl a - tay - lda ${hexVal(segment[0])} - sta ${segment[2].callLabel},y - lda ${hexValPlusOne(segment[0])} - sta ${segment[2].callLabel}+1,y - """ - }, - // uwordarray[index mem] = (u)word var - AsmPattern( - listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[1])} - asl a - tay - lda ${segment[0].callLabel} - sta ${segment[2].callLabel},y - lda ${segment[0].callLabel}+1 - sta ${segment[2].callLabel}+1,y - """ - }, - // uwordarray[index mem] = address-of var - AsmPattern( - listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[1])} - asl a - tay - lda #<${segment[0].callLabel} - sta ${segment[2].callLabel},y - lda #>${segment[0].callLabel} - sta ${segment[2].callLabel}+1,y - """ - }, - // uwordarray[index] = ubytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[2])*2 - when(segment[0].callLabel) { - "A" -> " sta ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index+1}" - "X" -> " stx ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index+1}" - "Y" -> " sty ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index+1}" - else -> " lda ${segment[0].callLabel} | sta ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index+1}" - } - }, - // wordarray[index] = bytevar (extend sign) - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[2])*2 - when(segment[0].callLabel) { - "A" -> - """ - sta ${segment[3].callLabel}+$index - ${signExtendA(segment[3].callLabel + "+${index+1}")} - """ - "X" -> - """ - txa - sta ${segment[3].callLabel}+$index - ${signExtendA(segment[3].callLabel + "+${index+1}")} - """ - "Y" -> - """ - tya - sta ${segment[3].callLabel}+$index - ${signExtendA(segment[3].callLabel + "+${index+1}")} - """ - else -> - """ - lda ${segment[0].callLabel} - sta ${segment[3].callLabel}+$index - ${signExtendA(segment[3].callLabel + "+${index+1}")} - """ - } - }, - // wordarray[index mem] = bytevar (extend sign) - AsmPattern( - listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - when(segment[0].callLabel) { - "A" -> - """ - pha - sty ${C64Zeropage.SCRATCH_B1} - lda ${hexVal(segment[2])} - asl a - tay - pla - sta ${segment[3].callLabel},y - ${signExtendA(segment[3].callLabel + "+1,y")} - """ - "X" -> - """ - stx ${C64Zeropage.SCRATCH_B1} - lda ${hexVal(segment[2])} - asl a - tay - lda ${C64Zeropage.SCRATCH_B1} - sta ${segment[3].callLabel},y - ${signExtendA(segment[3].callLabel + "+1,y")} - """ - "Y" -> - """ - sty ${C64Zeropage.SCRATCH_B1} - lda ${hexVal(segment[2])} - asl a - tay - lda ${C64Zeropage.SCRATCH_B1} - sta ${segment[3].callLabel},y - ${signExtendA(segment[3].callLabel + "+1,y")} - """ - else -> - """ - lda ${hexVal(segment[2])} - asl a - tay - lda ${segment[0].callLabel} - sta ${segment[3].callLabel},y - ${signExtendA(segment[3].callLabel + "+1,y")} - """ - } - }, - // wordarray[memory (u)byte] = ubyte mem - AsmPattern( - listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[2])} - asl a - tay - lda ${hexVal(segment[0])} - sta ${segment[3].callLabel},y - ${signExtendA(segment[3].callLabel + "+1,y")} - """ - }, - // wordarray[index] = mem byte (extend sign) - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[2])*2 - """ - lda ${hexVal(segment[0])} - sta ${segment[3].callLabel}+$index - ${signExtendA(segment[3].callLabel + "+${index+1}")} - """ - }, - // wordarray2[index2] = bytearray1[index1] (extend sign) - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index1 = intVal(segment[0]) - val index2 = segment[3].arg!!.integerValue()*2 - """ - lda ${segment[1].callLabel}+$index1 - sta ${segment[4].callLabel}+$index2 - ${signExtendA(segment[4].callLabel + "+${index2+1}")} - """ - }, - // wordarray2[mem (u)byte] = bytearray1[index1] (extend sign) - AsmPattern( - listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index1 = intVal(segment[0]) - """ - lda ${hexVal(segment[3])} - asl a - tay - lda ${segment[1].callLabel}+$index1 - sta ${segment[4].callLabel},y - ${signExtendA(segment[4].callLabel + "+1,y")} - """ - }, - - // wordarray[indexvar] = byte var (sign extended) - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val loadValueOnStack = when(segment[0].callLabel) { - "A" -> " pha" - "X" -> " txa | pha" - "Y" -> " tya | pha" - else -> " lda ${segment[0].callLabel} | pha" - } - val loadIndexY = when(segment[2].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[2].callLabel} | asl a | tay" - } - """ - $loadValueOnStack - $loadIndexY - pla - sta ${segment[3].callLabel},y - ${signExtendA(segment[3].callLabel + "+1,y")} - """ - }, - // wordarray[indexvar] = byte mem (sign extended) - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val loadIndexY = when(segment[2].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[2].callLabel} | asl a | tay" - } - """ - $loadIndexY - lda ${hexVal(segment[0])} - sta ${segment[3].callLabel},y - ${signExtendA(segment[3].callLabel + "+1,y")} - """ - }, - // wordarray[index] = mem word - AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[1])*2 - """ - lda ${hexVal(segment[0])} - sta ${segment[2].callLabel}+$index - lda ${hexValPlusOne(segment[0])} - sta ${segment[2].callLabel}+$index+1 - """ - }, - // wordarray2[indexvar] = bytearay[index] (sign extended) - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index = intVal(segment[0]) - val loadIndex2Y = when(segment[3].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[3].callLabel} | asl a | tay" - } - """ - $loadIndex2Y - lda ${segment[1].callLabel}+$index - sta ${segment[4].callLabel},y - lda ${segment[1].callLabel}+$index+1 - sta ${segment[4].callLabel}+1,y - """ - }, - // uwordarray[mem (u)byte] = mem word - AsmPattern( - listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[1])} - asl a - tay - lda ${hexVal(segment[0])} - sta ${segment[2].callLabel},y - lda ${hexValPlusOne(segment[0])} - sta ${segment[2].callLabel}+1,y - """ - }, - - // uwordarray[index mem] = ubytevar - AsmPattern( - listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - when(segment[0].callLabel) { - "A" -> - """ - pha - lda ${hexVal(segment[2])} - asl a - tay - pla - sta ${segment[3].callLabel},y - lda #0 - sta ${segment[3].callLabel}+1,y - """ - "X" -> - """ - lda ${hexVal(segment[2])} - asl a - tay - txa - sta ${segment[3].callLabel},y - lda #0 - sta ${segment[3].callLabel}+1,y - """ - "Y" -> - """ - lda ${hexVal(segment[2])} - asl a - stx ${C64Zeropage.SCRATCH_B1} - tax - tya - sta ${segment[3].callLabel},x - lda #0 - sta ${segment[3].callLabel}+1,x - ldx ${C64Zeropage.SCRATCH_B1} - """ - else -> - """ - lda ${hexVal(segment[2])} - asl a - tay - lda ${segment[0].callLabel} - sta ${segment[3].callLabel},y - lda #0 - sta ${segment[3].callLabel}+1,y - """ - } - }, - // uwordarray[index mem] = ubyte mem - AsmPattern( - listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - """ - lda ${hexVal(segment[2])} - asl a - tay - lda ${hexVal(segment[0])} - sta ${segment[3].callLabel},y - lda #0 - sta ${segment[3].callLabel}+1,y - """ - }, - // uwordarray[index] = mem ubyte - AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[2])*2 - """ - lda ${hexVal(segment[0])} - sta ${segment[3].callLabel}+$index - lda #0 - sta ${segment[3].callLabel}+${index+1} - """ - }, - // uwordarray[index] = (u)wordvar - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[1])*2 - " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}+$index | lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}+${index+1}" - }, - // uwordarray[index] = address-of var - AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[1])*2 - " lda #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} | sta ${segment[2].callLabel}+$index | sty ${segment[2].callLabel}+${index+1}" - }, - // uwordarray[index] = mem uword - AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val index = intVal(segment[1])*2 - """ - lda ${hexVal(segment[0])} - ldy ${hexValPlusOne(segment[0])} - sta ${segment[2].callLabel}+$index - sty ${segment[2].callLabel}+${index+1} - """ - }, - // uwordarray2[index2] = ubytearray1[index1] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index1 = intVal(segment[0]) - val index2 = segment[3].arg!!.integerValue()*2 - """ - lda ${segment[1].callLabel}+$index1 - sta ${segment[4].callLabel}+$index2 - lda #0 - sta ${segment[4].callLabel}+${index2+1} - """ - }, - // uwordarray2[index2] = (u)wordarray1[index1] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index1 = intVal(segment[0]) - val index2 = intVal(segment[2])*2 - """ - lda ${segment[1].callLabel}+$index1 - ldy ${segment[1].callLabel}+${index1+1} - sta ${segment[3].callLabel}+$index2 - sta ${segment[3].callLabel}+${index2+1} - """ - }, - // uwordarray[indexvar] = (u)word value - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val value = hexVal(segment[0]) - val loadIndexY = when(segment[1].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[1].callLabel} | asl a | tay" - } - " $loadIndexY | lda #<$value | sta ${segment[2].callLabel},y | lda #>$value | sta ${segment[2].callLabel}+1,y" - }, - // uwordarray[indexvar] = ubyte var - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val loadValueOnStack = when(segment[0].callLabel) { - "A" -> " pha" - "X" -> " txa | pha" - "Y" -> " tya | pha" - else -> " lda ${segment[0].callLabel} | pha" - } - val loadIndexY = when(segment[2].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[2].callLabel} | asl a | tay" - } - " $loadValueOnStack | $loadIndexY | pla | sta ${segment[3].callLabel},y | lda #0 | sta ${segment[3].callLabel}+1,y" - }, - // uwordarray[indexvar] = uword var - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val loadIndexY = when(segment[1].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[1].callLabel} | asl a | tay" - } - " $loadIndexY | lda ${segment[0].callLabel} | sta ${segment[2].callLabel},y | lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}+1,y" - }, - // uwordarray[indexvar] = address-of var - AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val loadIndexY = when(segment[1].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[1].callLabel} | asl a | tay" - } - " $loadIndexY | lda #<${segment[0].callLabel} | sta ${segment[2].callLabel},y | lda #>${segment[0].callLabel} | sta ${segment[2].callLabel}+1,y" - }, - // uwordarray[indexvar] = mem ubyte - AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val loadIndexY = when(segment[2].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[2].callLabel} | asl a | tay" - } - " $loadIndexY | lda ${hexVal(segment[0])} | sta ${segment[3].callLabel},y | lda #0 | sta ${segment[3].callLabel}+1,y" - }, - // uwordarray[indexvar] = mem (u)word - AsmPattern( - listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val loadIndexY = when(segment[1].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[1].callLabel} | asl a | tay" - } - " $loadIndexY | lda ${hexVal(segment[0])} | sta ${segment[2].callLabel},y | lda ${hexValPlusOne(segment[0])} | sta ${segment[2].callLabel}+1,y" - }, - // uwordarray2[indexvar] = ubytearay[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index = intVal(segment[0]) - val loadIndex2Y = when(segment[3].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[3].callLabel} | asl a | tay" - } - " $loadIndex2Y | lda ${segment[1].callLabel}+$index | sta ${segment[4].callLabel},y | lda #0 | sta ${segment[4].callLabel}+1,y" - }, - // uwordarray2[indexvar] = uwordarray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index = intVal(segment[0])*2 - val loadIndex2Y = when(segment[2].callLabel) { - "A" -> " asl a | tay" - "X" -> " txa | asl a | tay" - "Y" -> " tya | asl a | tay" - else -> " lda ${segment[2].callLabel} | asl a | tay" - } - " $loadIndex2Y | lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel},y | lda ${segment[1].callLabel}+${index+1} | sta ${segment[3].callLabel}+1,y" - }, - // uwordarray2[index mem] = ubytearray1[index1] - AsmPattern( - listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index1 = intVal(segment[0]) - """ - lda ${hexVal(segment[3])} - asl a - tay - lda ${segment[1].callLabel}+$index1 - sta ${segment[4].callLabel},y - lda #0 - sta ${segment[4].callLabel}+1,y - """ - }, - // uwordarray2[index mem] = uwordarray1[index1] - AsmPattern( - listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), - listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment-> - val index1 = intVal(segment[0]) - """ - lda ${hexVal(segment[2])} - asl a - tay - lda ${segment[1].callLabel}+$index1 - sta ${segment[3].callLabel},y - lda ${segment[1].callLabel}+${index1+1} - sta ${segment[3].callLabel}+1,y - """ - }, - - - // ----------- assignment to FLOAT VARIABLE ---------------- - // floatvar = ubytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - val loadByteA = when(segment[0].callLabel) { - "A" -> "" - "X" -> "txa" - "Y" -> "tya" - else -> "lda ${segment[0].callLabel}" - } - """ - $loadByteA - sta ${C64Zeropage.SCRATCH_B1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.ub2float - """ - }, - // floatvar = uwordvar - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - """ - lda ${segment[0].callLabel} - sta ${C64Zeropage.SCRATCH_W1} - lda ${segment[0].callLabel}+1 - sta ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.uw2float - """ - }, - // floatvar = bytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - val loadByteA = when(segment[0].callLabel) { - "A" -> "" - "X" -> "txa" - "Y" -> "tya" - else -> "lda ${segment[0].callLabel}" - } - """ - $loadByteA - sta ${C64Zeropage.SCRATCH_B1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.b2float - """ - }, - // floatvar = wordvar - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${C64Zeropage.SCRATCH_W1} - lda ${segment[0].callLabel}+1 - sta ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.w2float - """ - }, - // floatvar = float value - AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> - val floatConst = getFloatConst(segment[0].arg!!) - """ - lda #<$floatConst - ldy #>$floatConst - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[1].callLabel} - ldy #>${segment[1].callLabel} - jsr c64flt.copy_float - """ - }, - // floatvar = float var - AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> - """ - lda #<${segment[0].callLabel} - ldy #>${segment[0].callLabel} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[1].callLabel} - ldy #>${segment[1].callLabel} - jsr c64flt.copy_float - """ - }, - // floatvar = mem float - AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> - """ - lda #<${hexVal(segment[0])} - ldy #>${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[1].callLabel} - ldy #>${segment[1].callLabel} - jsr c64flt.copy_float - """ - }, - // floatvar = mem byte - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - """ - lda ${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_B1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.b2float - """ - }, - // floatvar = mem ubyte - AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - """ - lda ${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_B1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.ub2float - """ - }, - // floatvar = mem word - AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_W1} - lda ${hexValPlusOne(segment[0])} - sta ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.w2float - """ - }, - // floatvar = mem uword - AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_W1} - lda ${hexValPlusOne(segment[0])} - sta ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.uw2float - """ - }, - - // floatvar = bytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - val index = intVal(segment[0]) - """ - lda ${segment[1].callLabel}+$index - sta ${C64Zeropage.SCRATCH_B1} - lda #<${segment[3].callLabel} - ldy #>${segment[3].callLabel} - jsr c64flt.b2float - """ - }, - // floatvar = ubytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - val index = intVal(segment[0]) - """ - lda ${segment[1].callLabel}+$index - sta ${C64Zeropage.SCRATCH_B1} - lda #<${segment[3].callLabel} - ldy #>${segment[3].callLabel} - jsr c64flt.ub2float - """ - }, - // floatvar = wordarray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - val index = intVal(segment[0])*2 - """ - lda ${segment[1].callLabel}+$index - ldy ${segment[1].callLabel}+${index+1} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[3].callLabel} - ldy #>${segment[3].callLabel} - jsr c64flt.w2float - """ - }, - // floatvar = uwordarray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment-> - val index = intVal(segment[0])*2 - """ - lda ${segment[1].callLabel}+$index - ldy ${segment[1].callLabel}+${index+1} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[3].callLabel} - ldy #>${segment[3].callLabel} - jsr c64flt.uw2float - """ - }, - // floatvar = floatarray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> - val index = intVal(segment[0]) * Mflpt5.MemorySize - """ - lda #<${segment[1].callLabel}+$index - ldy #>${segment[1].callLabel}+$index - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${segment[2].callLabel} - ldy #>${segment[2].callLabel} - jsr c64flt.copy_float - """ - }, - - // memfloat = float value - AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> - val floatConst = getFloatConst(segment[0].arg!!) - """ - lda #<$floatConst - ldy #>$floatConst - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[1])} - ldy #>${hexVal(segment[1])} - jsr c64flt.copy_float - """ - }, - // memfloat = float var - AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> - """ - lda #<${segment[0].callLabel} - ldy #>${segment[0].callLabel} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[1])} - ldy #>${hexVal(segment[1])} - jsr c64flt.copy_float - """ - }, - // memfloat = ubytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - val loadByteA = when(segment[0].callLabel) { - "A" -> "" - "X" -> "txa" - "Y" -> "tya" - else -> "lda ${segment[0].callLabel}" - } - """ - $loadByteA - sta ${C64Zeropage.SCRATCH_B1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.ub2float - """ - }, - // memfloat = uwordvar - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - """ - lda ${segment[0].callLabel} - sta ${C64Zeropage.SCRATCH_W1} - lda ${segment[0].callLabel}+1 - sta ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.uw2float - """ - }, - // memfloat = bytevar - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - val loadByteA = when(segment[0].callLabel) { - "A" -> "" - "X" -> "txa" - "Y" -> "tya" - else -> "lda ${segment[0].callLabel}" - } - """ - $loadByteA - sta ${C64Zeropage.SCRATCH_B1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.b2float - """ - }, - // memfloat = wordvar - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${C64Zeropage.SCRATCH_W1} - lda ${segment[0].callLabel}+1 - sta ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.w2float - """ - }, - // memfloat = mem byte - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - """ - lda ${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_B1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.b2float - """ - }, - // memfloat = mem ubyte - AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - """ - lda ${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_B1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.ub2float - """ - }, - // memfloat = mem word - AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_W1} - lda ${hexValPlusOne(segment[0])} - sta ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.w2float - """ - }, - // memfloat = mem uword - AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> - """ - lda ${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_W1} - lda ${hexValPlusOne(segment[0])} - sta ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.uw2float - """ - }, - // memfloat = mem float - AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> - """ - lda #<${hexVal(segment[0])} - ldy #>${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[1])} - ldy #>${hexVal(segment[1])} - jsr c64flt.copy_float - """ - }, - // memfloat = bytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - val index = intVal(segment[0]) - """ - lda ${segment[1].callLabel}+$index - sta ${C64Zeropage.SCRATCH_B1} - lda #<${hexVal(segment[3])} - ldy #>${hexVal(segment[3])} - jsr c64flt.b2float - """ - }, - // memfloat = ubytearray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - val index = intVal(segment[0]) - """ - lda ${segment[1].callLabel}+$index - sta ${C64Zeropage.SCRATCH_B1} - lda #<${hexVal(segment[3])} - ldy #>${hexVal(segment[3])} - jsr c64flt.ub2float - """ - }, - // memfloat = wordarray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - val index = intVal(segment[0])*2 - """ - lda ${segment[1].callLabel}+$index - ldy ${segment[1].callLabel}+${index+1} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[3])} - ldy #>${hexVal(segment[3])} - jsr c64flt.w2float - """ - }, - // memfloat = uwordarray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment-> - val index = intVal(segment[0])*2 - """ - lda ${segment[1].callLabel}+$index - ldy ${segment[1].callLabel}+${index+1} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[3])} - ldy #>${hexVal(segment[3])} - jsr c64flt.uw2float - """ - }, - // memfloat = floatarray[index] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> - val index = intVal(segment[0]) * Mflpt5.MemorySize - """ - lda #<${segment[1].callLabel}+$index - ldy #>${segment[1].callLabel}+$index - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<${hexVal(segment[2])} - ldy #>${hexVal(segment[2])} - jsr c64flt.copy_float - """ - }, - // floatarray[idxbyte] = float - AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> - val floatConst = getFloatConst(segment[0].arg!!) - val index = intVal(segment[1]) * Mflpt5.MemorySize - """ - lda #<$floatConst - ldy #>$floatConst - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<(${segment[2].callLabel}+$index) - ldy #>(${segment[2].callLabel}+$index) - jsr c64flt.copy_float - """ - }, - // floatarray[idxbyte] = floatvar - AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> - val index = intVal(segment[1]) * Mflpt5.MemorySize - """ - lda #<${segment[0].callLabel} - ldy #>${segment[0].callLabel} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<(${segment[2].callLabel}+$index) - ldy #>(${segment[2].callLabel}+$index) - jsr c64flt.copy_float - """ - }, - // floatarray[idxbyte] = memfloat - AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> - val index = intVal(segment[1]) * Mflpt5.MemorySize - """ - lda #<${hexVal(segment[0])} - ldy #>${hexVal(segment[0])} - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<(${segment[2].callLabel}+$index) - ldy #>(${segment[2].callLabel}+$index) - jsr c64flt.copy_float - """ - }, - // floatarray[idx2] = floatarray[idx1] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> - val index1 = intVal(segment[0]) * Mflpt5.MemorySize - val index2 = intVal(segment[2]) * Mflpt5.MemorySize - """ - lda #<(${segment[1].callLabel}+$index1) - ldy #>(${segment[1].callLabel}+$index1) - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} - lda #<(${segment[3].callLabel}+$index2) - ldy #>(${segment[3].callLabel}+$index2) - jsr c64flt.copy_float - """ - }, - - // ---------- some special operations ------------------ - // var word = AX register pair - AsmPattern(listOf(Opcode.PUSH_REGAX_WORD, Opcode.POP_VAR_WORD)) { segment -> - """ - sta ${segment[1].callLabel} - stx ${segment[1].callLabel}+1 - """ - }, - // var word = AY register pair - AsmPattern(listOf(Opcode.PUSH_REGAY_WORD, Opcode.POP_VAR_WORD)) { segment -> - """ - sta ${segment[1].callLabel} - sty ${segment[1].callLabel}+1 - """ - }, - // var word = XY register pair - AsmPattern(listOf(Opcode.PUSH_REGXY_WORD, Opcode.POP_VAR_WORD)) { segment -> - """ - stx ${segment[1].callLabel} - sty ${segment[1].callLabel}+1 - """ - }, - // mem word = AX register pair - AsmPattern(listOf(Opcode.PUSH_REGAX_WORD, Opcode.POP_MEM_WORD)) { segment -> - """ - sta ${hexVal(segment[1])} - stx ${hexValPlusOne(segment[1])} - """ - }, - // mem word = AY register pair - AsmPattern(listOf(Opcode.PUSH_REGAY_WORD, Opcode.POP_MEM_WORD)) { segment -> - """ - sta ${hexVal(segment[1])} - sty ${hexValPlusOne(segment[1])} - """ - }, - // mem word = XY register pair - AsmPattern(listOf(Opcode.PUSH_REGXY_WORD, Opcode.POP_MEM_WORD)) { segment -> - """ - stx ${hexVal(segment[1])} - sty ${hexValPlusOne(segment[1])} - """ - }, - - // AX register pair = word value - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGAX_WORD)) { segment -> - val value = hexVal(segment[0]) - " lda #<$value | ldx #>$value" - }, - // AY register pair = word value - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGAY_WORD)) { segment -> - val value = hexVal(segment[0]) - " lda #<$value | ldy #>$value" - }, - // XY register pair = word value - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGXY_WORD)) { segment -> - val value = hexVal(segment[0]) - " ldx #<$value | ldy #>$value" - }, - // AX register pair = word var - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGAX_WORD)) { segment -> - " lda ${segment[0].callLabel} | ldx ${segment[0].callLabel}+1" - }, - // AY register pair = word var - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGAY_WORD)) { segment -> - " lda ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1" - }, - // XY register pair = word var - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGXY_WORD)) { segment -> - " ldx ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1" - }, - // AX register pair = mem word - AsmPattern( - listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGAX_WORD), - listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGAX_WORD)) { segment -> - " lda ${hexVal(segment[0])} | ldx ${hexValPlusOne(segment[0])}" - }, - // AY register pair = mem word - AsmPattern( - listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGAY_WORD), - listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGAY_WORD)) { segment -> - " lda ${hexVal(segment[0])} | ldy ${hexValPlusOne(segment[0])}" - }, - // XY register pair = mem word - AsmPattern( - listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGXY_WORD), - listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGXY_WORD)) { segment -> - " ldx ${hexVal(segment[0])} | ldy ${hexValPlusOne(segment[0])}" - }, - - - // byte var = wordvar as (u)byte - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_UB, Opcode.POP_VAR_BYTE), - listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_B, Opcode.POP_VAR_BYTE)) { segment -> - when(segment[2].callLabel) { - "A" -> " lda ${segment[0].callLabel}" - "X" -> " ldx ${segment[0].callLabel}" - "Y" -> " ldy ${segment[0].callLabel}" - else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}" - } - }, - // byte var = uwordvar as (u)byte - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_UB, Opcode.POP_VAR_BYTE), - listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_B, Opcode.POP_VAR_BYTE)) { segment -> - when(segment[2].callLabel) { - "A" -> " lda ${segment[0].callLabel}" - "X" -> " ldx ${segment[0].callLabel}" - "Y" -> " ldy ${segment[0].callLabel}" - else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}" - } - }, - // byte var = msb(word var) - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.MSB, Opcode.POP_VAR_BYTE)) { segment -> - when(segment[2].callLabel) { - "A" -> " lda ${segment[0].callLabel}+1" - "X" -> " ldx ${segment[0].callLabel}+1" - "Y" -> " ldy ${segment[0].callLabel}+1" - else -> " lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}" - } - }, - // push word var as (u)byte - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_UB), - listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_B)) { segment -> - " lda ${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex " - }, - // push uword var as (u)byte - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_UB), - listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_B)) { segment -> - " lda ${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex " - }, - // push msb(word var) - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.MSB)) { segment -> - " lda ${segment[0].callLabel}+1 | sta ${ESTACK_LO.toHex()},x | dex " - }, - - // set a register pair to a certain memory address (of a variable) - AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGAX_WORD)) { segment -> - " lda #<${segment[0].callLabel} | ldx #>${segment[0].callLabel} " - }, - AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGAY_WORD)) { segment -> - " lda #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} " - }, - AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGXY_WORD)) { segment -> - " ldx #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} " - }, - - // push memory byte | bytevalue - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE)) { segment -> - " lda ${hexVal(segment[0])} | ora #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " - }, - // push memory byte & bytevalue - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE)) { segment -> - " lda ${hexVal(segment[0])} | and #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " - }, - // push memory byte ^ bytevalue - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment -> - " lda ${hexVal(segment[0])} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " - }, - // push var byte | bytevalue - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE)) { segment -> - " lda ${segment[0].callLabel} | ora #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " - }, - // push var byte & bytevalue - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE)) { segment -> - " lda ${segment[0].callLabel} | and #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " - }, - // push var byte ^ bytevalue - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment -> - " lda ${segment[0].callLabel} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " - }, - - // push memory word | wordvalue - AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITOR_WORD), - listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITOR_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - ora #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x - lda ${hexValPlusOne(segment[0])} - ora #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - // push memory word & wordvalue - AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITAND_WORD), - listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITAND_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - and #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x - lda ${hexValPlusOne(segment[0])} - and #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - // push memory word ^ wordvalue - AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITXOR_WORD), - listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITXOR_WORD)) { segment -> - """ - lda ${hexVal(segment[0])} - eor #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x - lda ${hexValPlusOne(segment[0])} - eor #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - // push var word | wordvalue - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITOR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - ora #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x - lda ${segment[0].callLabel}+1 - ora #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - // push var word & wordvalue - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITAND_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - and #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x - lda ${segment[0].callLabel}+1 - and #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - // push var word ^ wordvalue - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITXOR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - eor #<${hexVal(segment[1])} - sta ${ESTACK_LO.toHex()},x - lda ${segment[0].callLabel}+1 - eor #>${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - // push var byte & var byte - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITAND_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - """ - lda ${segment[0].callLabel} - and ${segment[1].callLabel} - sta ${segment[3].callLabel} - """ - }, - // push var byte | var byte - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITOR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - """ - lda ${segment[0].callLabel} - ora ${segment[1].callLabel} - sta ${segment[3].callLabel} - """ - }, - // push var byte ^ var byte - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITXOR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - """ - lda ${segment[0].callLabel} - eor ${segment[1].callLabel} - sta ${segment[3].callLabel} - """ - }, - // push var word & var word - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITAND_WORD, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - and ${segment[1].callLabel} - sta ${segment[3].callLabel} - lda ${segment[0].callLabel}+1 - and ${segment[1].callLabel}+1 - sta ${segment[3].callLabel}+1 - """ - }, - // push var word | var word - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITOR_WORD, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - ora ${segment[1].callLabel} - sta ${segment[3].callLabel} - lda ${segment[0].callLabel}+1 - ora ${segment[1].callLabel}+1 - sta ${segment[3].callLabel}+1 - """ - }, - // push var word ^ var word - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITXOR_WORD, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - eor ${segment[1].callLabel} - sta ${segment[3].callLabel} - lda ${segment[0].callLabel}+1 - eor ${segment[1].callLabel}+1 - sta ${segment[3].callLabel}+1 - """ - }, - - // bytearray[consti3] = bytearray[consti1] ^ bytearray[consti2] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, - Opcode.BITXOR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val i1 = segment[5].arg!!.integerValue() - val i2 = segment[0].arg!!.integerValue() - val i3 = segment[2].arg!!.integerValue() - """ - lda ${segment[1].callLabel}+$i2 - eor ${segment[3].callLabel}+$i3 - sta ${segment[6].callLabel}+$i1 - """ - }, - // warray[consti3] = warray[consti1] ^ warray[consti2] - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, - Opcode.BITXOR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val i1 = segment[5].arg!!.integerValue()*2 - val i2 = segment[0].arg!!.integerValue()*2 - val i3 = segment[2].arg!!.integerValue()*2 - """ - lda ${segment[1].callLabel}+$i2 - eor ${segment[3].callLabel}+$i3 - sta ${segment[6].callLabel}+$i1 - lda ${segment[1].callLabel}+${i2+1} - eor ${segment[3].callLabel}+${i3+1} - sta ${segment[6].callLabel}+${i1+1} - """ - }, - - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${ESTACK_LO.toHex()},x - lda ${segment[1].callLabel} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment -> - """ - lda #${hexVal(segment[0])} - sta ${ESTACK_LO.toHex()},x - lda ${segment[1].callLabel} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.MKWORD)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${ESTACK_LO.toHex()},x - lda #${hexVal(segment[1])} - sta ${ESTACK_HI.toHex()},x - dex - """ - }, - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${segment[3].callLabel} - lda ${segment[1].callLabel} - sta ${segment[3].callLabel}+1 - """ - }, - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.MKWORD, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${segment[3].callLabel} - lda #${hexVal(segment[1])} - sta ${segment[3].callLabel}+1 - """ - }, - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD, Opcode.POP_VAR_WORD)) { segment -> - """ - lda #${hexVal(segment[0])} - sta ${segment[3].callLabel} - lda ${segment[1].callLabel} - sta ${segment[3].callLabel}+1 - """ - }, - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD, Opcode.CAST_UW_TO_W, Opcode.POP_VAR_WORD)) { segment -> - """ - lda ${segment[0].callLabel} - sta ${segment[4].callLabel} - lda ${segment[1].callLabel} - sta ${segment[4].callLabel}+1 - """ - }, - - // more efficient versions of x+1 and x-1 to avoid pushing the 1 on the stack - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.ADD_B), listOf(Opcode.PUSH_BYTE, Opcode.ADD_UB)) { segment -> - val amount = segment[0].arg!!.integerValue() - if(amount in 1..2) { - " inc ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) - } - else - null - }, - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.ADD_UW), listOf(Opcode.PUSH_WORD, Opcode.ADD_W)) { segment -> - val amount = segment[0].arg!!.integerValue() - if(amount in 1..2) { - " inc ${(ESTACK_LO + 1).toHex()},x | bne + | inc ${(ESTACK_HI + 1).toHex()},x |+ | ".repeat(amount) - } - else - null - }, - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.SUB_B), listOf(Opcode.PUSH_BYTE, Opcode.SUB_UB)) { segment -> - val amount = segment[0].arg!!.integerValue() - if(amount in 1..2) { - " dec ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) - } - else - null - }, - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.SUB_UW), listOf(Opcode.PUSH_WORD, Opcode.SUB_W)) { segment -> - val amount = segment[0].arg!!.integerValue() - if(amount in 1..2) { - " lda ${(ESTACK_LO + 1).toHex()},x | bne + | dec ${(ESTACK_HI + 1).toHex()},x |+ | dec ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) - } - else - null - }, - - // @todo optimize 8 and 16 bit adds and subs (avoid stack use altogether on most common operations) - - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CMP_B), listOf(Opcode.PUSH_VAR_BYTE, Opcode.CMP_UB)) { segment -> - // this pattern is encountered as part of the loop bound condition in for loops (var + cmp + jz/jnz) - val cmpval = segment[1].arg!!.integerValue() - " lda ${segment[0].callLabel} | cmp #$cmpval " - }, - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CMP_W), listOf(Opcode.PUSH_VAR_WORD, Opcode.CMP_UW)) { segment -> - // this pattern is encountered as part of the loop bound condition in for loops (var + cmp + jz/jnz) - """ - lda ${segment[0].callLabel} - cmp #<${hexVal(segment[1])} - bne + - lda ${segment[0].callLabel}+1 - cmp #>${hexVal(segment[1])} - bne + - lda #0 -+ - """ - }, - - AsmPattern(listOf(Opcode.RRESTOREX, Opcode.LINE, Opcode.RSAVEX), listOf(Opcode.RRESTOREX, Opcode.RSAVEX)) { segment -> - """ - sta ${C64Zeropage.SCRATCH_REG} - pla - tax - pha - lda ${C64Zeropage.SCRATCH_REG} - """ - }, - - // various optimizable integer multiplications - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.MUL_B), listOf(Opcode.PUSH_BYTE, Opcode.MUL_UB)) { segment -> - val amount=segment[0].arg!!.integerValue() - val result = optimizedIntMultiplicationsOnStack(segment[1], amount) - result ?: " lda #${hexVal(segment[0])} | sta ${ESTACK_LO.toHex()},x | dex | jsr prog8_lib.mul_byte" - }, - AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.MUL_W), listOf(Opcode.PUSH_WORD, Opcode.MUL_UW)) { segment -> - val amount=segment[0].arg!!.integerValue() - val result = optimizedIntMultiplicationsOnStack(segment[1], amount) - if (result != null) result else { - val value = hexVal(segment[0]) - " lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex | jsr prog8_lib.mul_word" - } - }, - - // various variable or memory swaps - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.POP_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> - val var1 = segment[0].callLabel - val var2 = segment[1].callLabel - val var3 = segment[2].callLabel - val var4 = segment[3].callLabel - if(var1==var3 && var2==var4) { - """ - lda $var1 - tay - lda $var2 - sta $var1 - sty $var2 - """ - } else null - }, - AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.POP_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> - val var1 = segment[0].callLabel - val var2 = segment[1].callLabel - val var3 = segment[2].callLabel - val var4 = segment[3].callLabel - if(var1==var3 && var2==var4) { - """ - lda $var1 - tay - lda $var2 - sta $var1 - sty $var2 - lda $var1+1 - tay - lda $var2+1 - sta $var1+1 - sty $var2+1 - """ - } else null - }, - AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_B, Opcode.POP_MEM_BYTE, Opcode.POP_MEM_BYTE), - listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_MEM_UB, Opcode.POP_MEM_BYTE, Opcode.POP_MEM_BYTE)) { segment -> - val addr1 = segment[0].arg!!.integerValue() - val addr2 = segment[1].arg!!.integerValue() - val addr3 = segment[2].arg!!.integerValue() - val addr4 = segment[3].arg!!.integerValue() - if(addr1==addr3 && addr2==addr4) { - """ - lda ${addr1.toHex()} - tay - lda ${addr2.toHex()} - sta ${addr1.toHex()} - sty ${addr2.toHex()} - """ - } else null - }, - AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_W, Opcode.POP_MEM_WORD, Opcode.POP_MEM_WORD), - listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_MEM_UW, Opcode.POP_MEM_WORD, Opcode.POP_MEM_WORD)) { segment -> - val addr1 = segment[0].arg!!.integerValue() - val addr2 = segment[1].arg!!.integerValue() - val addr3 = segment[2].arg!!.integerValue() - val addr4 = segment[3].arg!!.integerValue() - if(addr1==addr3 && addr2==addr4) { - """ - lda ${addr1.toHex()} - tay - lda ${addr2.toHex()} - sta ${addr1.toHex()} - sty ${addr2.toHex()} - lda ${(addr1+1).toHex()} - tay - lda ${(addr2+1).toHex()} - sta ${(addr1+1).toHex()} - sty ${(addr2+1).toHex()} - """ - } else null - }, - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, - Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val i1 = segment[0].arg!!.integerValue() - val i2 = segment[2].arg!!.integerValue() - val i3 = segment[4].arg!!.integerValue() - val i4 = segment[6].arg!!.integerValue() - val array1 = segment[1].callLabel - val array2 = segment[3].callLabel - val array3 = segment[5].callLabel - val array4 = segment[7].callLabel - if(i1==i3 && i2==i4 && array1==array3 && array2==array4) { - """ - lda $array1+$i1 - tay - lda $array2+$i2 - sta $array1+$i1 - sty $array2+$i2 - """ - } else null - }, - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, - Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> - val vi1 = segment[0].callLabel - val vi2 = segment[2].callLabel - val vi3 = segment[4].callLabel - val vi4 = segment[6].callLabel - val array1 = segment[1].callLabel - val array2 = segment[3].callLabel - val array3 = segment[5].callLabel - val array4 = segment[7].callLabel - if(vi1==vi3 && vi2==vi4 && array1==array3 && array2==array4) { - val load1 = loadAFromIndexedByVar(segment[0], segment[1]) - val load2 = loadAFromIndexedByVar(segment[2], segment[3]) - val storeIn1 = storeAToIndexedByVar(segment[0], segment[1]) - val storeIn2 = storeAToIndexedByVar(segment[2], segment[3]) - """ - $load1 - pha - $load2 - $storeIn1 - pla - $storeIn2 - """ - } else null - }, - AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, - Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val i1 = segment[0].arg!!.integerValue()*2 - val i2 = segment[2].arg!!.integerValue()*2 - val i3 = segment[4].arg!!.integerValue()*2 - val i4 = segment[6].arg!!.integerValue()*2 - val array1 = segment[1].callLabel - val array2 = segment[3].callLabel - val array3 = segment[5].callLabel - val array4 = segment[7].callLabel - if(i1==i3 && i2==i4 && array1==array3 && array2==array4) { - """ - lda $array1+$i1 - tay - lda $array2+$i2 - sta $array1+$i1 - sty $array2+$i2 - lda $array1+${i1+1} - tay - lda $array2+${i2+1} - sta $array1+${i1+1} - sty $array2+${i2+1} - """ - } else null - }, - AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, - Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> - val vi1 = segment[0].callLabel - val vi2 = segment[2].callLabel - val vi3 = segment[4].callLabel - val vi4 = segment[6].callLabel - val array1 = segment[1].callLabel - val array2 = segment[3].callLabel - val array3 = segment[5].callLabel - val array4 = segment[7].callLabel - if(vi1==vi3 && vi2==vi4 && array1==array3 && array2==array4) { - // SCRATCH_B1 = index1 - // SCRATCH_REG = index2 - // SCRATCH_W1 = temp storage of array[index2] - """ - lda ${segment[0].callLabel} - asl a - sta ${C64Zeropage.SCRATCH_B1} - lda ${segment[2].callLabel} - asl a - sta ${C64Zeropage.SCRATCH_REG} - stx ${C64Zeropage.SCRATCH_REG_X} - tax - lda ${segment[3].callLabel},x - ldy ${segment[3].callLabel}+1,x - sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1}+1 - ldx ${C64Zeropage.SCRATCH_B1} - lda ${segment[1].callLabel},x - ldy ${segment[1].callLabel}+1,x - ldx ${C64Zeropage.SCRATCH_REG} - sta ${segment[3].callLabel},x - tya - sta ${segment[3].callLabel}+1,x - ldx ${C64Zeropage.SCRATCH_B1} - lda ${C64Zeropage.SCRATCH_W1} - sta ${segment[1].callLabel},x - lda ${C64Zeropage.SCRATCH_W1}+1 - sta ${segment[1].callLabel}+1,x - ldx ${C64Zeropage.SCRATCH_REG_X} - """ - } else null - } - - - ) - } diff --git a/compiler/src/prog8/compiler/target/c64/AsmPatterns.kt b/compiler/src/prog8/compiler/target/c64/AsmPatterns.kt new file mode 100644 index 000000000..852dc99cf --- /dev/null +++ b/compiler/src/prog8/compiler/target/c64/AsmPatterns.kt @@ -0,0 +1,2294 @@ +package prog8.compiler.target.c64 + +import prog8.ast.base.printWarning +import prog8.compiler.intermediate.Instruction +import prog8.compiler.intermediate.Opcode +import prog8.compiler.toHex + +internal class AsmPattern(val sequence: List, val altSequence: List?=null, val asm: (List)->String?) + +internal fun loadAFromIndexedByVar(idxVarInstr: Instruction, readArrayInstr: Instruction): String { + // A = readArrayInstr [ idxVarInstr ] + return when (idxVarInstr.callLabel) { + "A" -> " tay | lda ${readArrayInstr.callLabel},y" + "X" -> " txa | tay | lda ${readArrayInstr.callLabel},y" + "Y" -> " lda ${readArrayInstr.callLabel},y" + else -> " ldy ${idxVarInstr.callLabel} | lda ${readArrayInstr.callLabel},y" + } +} + +internal fun loadAYFromWordIndexedByVar(idxVarInstr: Instruction, readArrayInstr: Instruction): String { + // AY = readWordArrayInstr [ idxVarInstr ] + return when(idxVarInstr.callLabel) { + "A" -> + """ + stx ${C64Zeropage.SCRATCH_B1} + asl a + tax + lda ${readArrayInstr.callLabel},x + ldy ${readArrayInstr.callLabel}+1,x + ldx ${C64Zeropage.SCRATCH_B1} + """ + "X" -> + """ + stx ${C64Zeropage.SCRATCH_B1} + txa + asl a + tax + lda ${readArrayInstr.callLabel},x + ldy ${readArrayInstr.callLabel}+1,x + ldx ${C64Zeropage.SCRATCH_B1} + """ + "Y" -> + """ + stx ${C64Zeropage.SCRATCH_B1} + tya + asl a + tax + lda ${readArrayInstr.callLabel},x + ldy ${readArrayInstr.callLabel}+1,x + ldx ${C64Zeropage.SCRATCH_B1} + """ + else -> + """ + stx ${C64Zeropage.SCRATCH_B1} + lda ${idxVarInstr.callLabel} + asl a + tax + lda ${readArrayInstr.callLabel},x + ldy ${readArrayInstr.callLabel}+1,x + ldx ${C64Zeropage.SCRATCH_B1} + """ + } +} + +internal fun storeAToIndexedByVar(idxVarInstr: Instruction, writeArrayInstr: Instruction): String { + // writeArrayInstr [ idxVarInstr ] = A + return when (idxVarInstr.callLabel) { + "A" -> " tay | sta ${writeArrayInstr.callLabel},y" + "X" -> " stx ${C64Zeropage.SCRATCH_B1} | ldy ${C64Zeropage.SCRATCH_B1} | sta ${writeArrayInstr.callLabel},y" + "Y" -> " sta ${writeArrayInstr.callLabel},y" + else -> " ldy ${idxVarInstr.callLabel} | sta ${writeArrayInstr.callLabel},y" + } +} + +internal fun optimizedIntMultiplicationsOnStack(mulIns: Instruction, amount: Int): String? { + + if(mulIns.opcode == Opcode.MUL_B || mulIns.opcode==Opcode.MUL_UB) { + if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) + printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount") + if(amount in setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40)) + return " jsr math.mul_byte_$amount" + if(mulIns.opcode == Opcode.MUL_B && amount in setOf(-3,-5,-6,-7,-9,-10,-11,-12,-13,-14,-15,-20,-25,-40)) + return " jsr prog8_lib.neg_b | jsr math.mul_byte_${-amount}" + } + else if(mulIns.opcode == Opcode.MUL_UW) { + if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) + printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount") + if(amount in setOf(3,5,6,7,9,10,12,15,20,25,40)) + return " jsr math.mul_word_$amount" + } + else if(mulIns.opcode == Opcode.MUL_W) { + if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) + printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount") + if(amount in setOf(3,5,6,7,9,10,12,15,20,25,40)) + return " jsr math.mul_word_$amount" + if(amount in setOf(-3,-5,-6,-7,-9,-10,-12,-15,-20,-25,-40)) + return " jsr prog8_lib.neg_w | jsr math.mul_word_${-amount}" + } + + return null +} + +internal val patterns = listOf( + // ----------- assignment to BYTE VARIABLE ---------------- + // var = (u)bytevalue + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + when (segment[1].callLabel) { + "A", "X", "Y" -> + " ld${segment[1].callLabel!!.toLowerCase()} #${hexVal(segment[0])}" + else -> + " lda #${hexVal(segment[0])} | sta ${segment[1].callLabel}" + } + }, + // var = other var + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + when (segment[1].callLabel) { + "A" -> + when (segment[0].callLabel) { + "A" -> null + "X" -> " txa" + "Y" -> " tya" + else -> " lda ${segment[0].callLabel}" + } + "X" -> + when (segment[0].callLabel) { + "A" -> " tax" + "X" -> null + "Y" -> " tya | tax" + else -> " ldx ${segment[0].callLabel}" + } + "Y" -> + when (segment[0].callLabel) { + "A" -> " tay" + "X" -> " txa | tay" + "Y" -> null + else -> " ldy ${segment[0].callLabel}" + } + else -> + when (segment[0].callLabel) { + "A" -> " sta ${segment[1].callLabel}" + "X" -> " stx ${segment[1].callLabel}" + "Y" -> " sty ${segment[1].callLabel}" + else -> " lda ${segment[0].callLabel} | sta ${segment[1].callLabel}" + } + } + }, + // var = mem (u)byte + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.POP_VAR_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.POP_VAR_BYTE)) { segment -> + when (segment[1].callLabel) { + "A", "X", "Y" -> " ld${segment[1].callLabel!!.toLowerCase()} ${hexVal(segment[0])}" + else -> " lda ${hexVal(segment[0])} | sta ${segment[1].callLabel}" + } + }, + // var = (u)bytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + val index = intVal(segment[0]) + when (segment[2].callLabel) { + "A", "X", "Y" -> + " ld${segment[2].callLabel!!.toLowerCase()} ${segment[1].callLabel}+$index" + else -> + " lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel}" + } + }, + // var = (u)bytearray[indexvar] + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) + when (segment[2].callLabel) { + "A" -> " $loadByteA" + "X" -> " $loadByteA | tax" + "Y" -> " $loadByteA | tay" + else -> " $loadByteA | sta ${segment[2].callLabel}" + } + }, + // var = (u)bytearray[mem index var] + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + val loadByteA = " ldy ${hexVal(segment[0])} | lda ${segment[1].callLabel},y" + when (segment[2].callLabel) { + "A" -> " $loadByteA" + "X" -> " $loadByteA | tax" + "Y" -> " $loadByteA | tay" + else -> " $loadByteA | sta ${segment[2].callLabel}" + } + }, + + + // ----------- assignment to BYTE MEMORY ---------------- + // mem = (u)byte value + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_BYTE)) { segment -> + " lda #${hexVal(segment[0])} | sta ${hexVal(segment[1])}" + }, + // mem = (u)bytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_BYTE)) { segment -> + when (segment[0].callLabel) { + "A" -> " sta ${hexVal(segment[1])}" + "X" -> " stx ${hexVal(segment[1])}" + "Y" -> " sty ${hexVal(segment[1])}" + else -> " lda ${segment[0].callLabel} | sta ${hexVal(segment[1])}" + } + }, + // mem = mem (u)byte + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.POP_MEM_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.POP_MEM_BYTE)) { segment -> + " lda ${hexVal(segment[0])} | sta ${hexVal(segment[1])}" + }, + // mem = (u)bytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_BYTE)) { segment -> + val address = hexVal(segment[2]) + val index = intVal(segment[0]) + " lda ${segment[1].callLabel}+$index | sta $address" + }, + // mem = (u)bytearray[indexvar] + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_BYTE)) { segment -> + val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) + " $loadByteA | sta ${hexVal(segment[2])}" + }, + // mem = (u)bytearray[mem index var] + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_BYTE)) { segment -> + """ + ldy ${hexVal(segment[0])} + lda ${segment[1].callLabel},y + sta ${hexVal(segment[2])} + """ + }, + + + // ----------- assignment to BYTE ARRAY ---------------- + // bytearray[index] = (u)byte value + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val index = intVal(segment[1]) + val value = hexVal(segment[0]) + " lda #$value | sta ${segment[2].callLabel}+$index" + }, + // bytearray[index] = (u)bytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val index = intVal(segment[1]) + when (segment[0].callLabel) { + "A" -> " sta ${segment[2].callLabel}+$index" + "X" -> " stx ${segment[2].callLabel}+$index" + "Y" -> " sty ${segment[2].callLabel}+$index" + else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}+$index" + } + }, + // bytearray[index] = mem(u)byte + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val index = intVal(segment[1]) + " lda ${hexVal(segment[0])} | sta ${segment[2].callLabel}+$index" + }, + + // bytearray[index var] = (u)byte value + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val storeA = storeAToIndexedByVar(segment[1], segment[2]) + " lda #${hexVal(segment[0])} | $storeA" + }, + // (u)bytearray[index var] = (u)bytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val storeA = storeAToIndexedByVar(segment[1], segment[2]) + when (segment[0].callLabel) { + "A" -> " $storeA" + "X" -> " txa | $storeA" + "Y" -> " tya | $storeA" + else -> " lda ${segment[0].callLabel} | $storeA" + } + }, + // (u)bytearray[index var] = mem (u)byte + AsmPattern( + listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE), + listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val storeA = storeAToIndexedByVar(segment[1], segment[2]) + " lda ${hexVal(segment[0])} | $storeA" + }, + + // bytearray[index mem] = (u)byte value + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + """ + lda #${hexVal(segment[0])} + ldy ${hexVal(segment[1])} + sta ${segment[2].callLabel},y + """ + }, + // bytearray[index mem] = (u)byte var + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val loadY = " ldy ${hexVal(segment[1])}" + when (segment[0].callLabel) { + "A" -> " $loadY | sta ${segment[2].callLabel},y" + "X" -> " txa | $loadY | sta ${segment[2].callLabel},y" + "Y" -> " tya | $loadY | sta ${segment[2].callLabel},y" + else -> " lda ${segment[0].callLabel} | $loadY | sta ${segment[2].callLabel},y" + } + }, + // bytearray[index mem] = mem(u)byte + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + """ + ldy ${hexVal(segment[1])} + lda ${hexVal(segment[0])} + sta ${segment[2].callLabel},y + """ + }, + + // (u)bytearray2[index2] = (u)bytearray1[index1] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val index1 = intVal(segment[0]) + val index2 = intVal(segment[2]) + " lda ${segment[1].callLabel}+$index1 | sta ${segment[3].callLabel}+$index2" + }, + // (u)bytearray2[index2] = (u)bytearray[indexvar] + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) + val index2 = intVal(segment[2]) + " $loadByteA | sta ${segment[3].callLabel}+$index2" + }, + // (u)bytearray[index2] = (u)bytearray[mem ubyte] + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val index2 = intVal(segment[2]) + """ + ldy ${hexVal(segment[0])} + lda ${segment[1].callLabel},y + sta ${segment[3].callLabel}+$index2 + """ + }, + + // (u)bytearray2[idxvar2] = (u)bytearray1[index1] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val storeA = storeAToIndexedByVar(segment[2], segment[3]) + val index1 = intVal(segment[0]) + " lda ${segment[1].callLabel}+$index1 | $storeA" + }, + // (u)bytearray2[idxvar2] = (u)bytearray1[idxvar] + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val loadA = loadAFromIndexedByVar(segment[0], segment[1]) + val storeA = storeAToIndexedByVar(segment[2], segment[3]) + " $loadA | $storeA" + }, + // (u)bytearray2[idxvar2] = (u)bytearray1[mem ubyte] + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val storeA = storeAToIndexedByVar(segment[2], segment[3]) + " ldy ${hexVal(segment[0])} | lda ${segment[1].callLabel},y | $storeA" + }, + + // (u)bytearray2[index mem] = (u)bytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val index1 = intVal(segment[0]) + """ + lda ${segment[1].callLabel}+$index1 + ldy ${hexVal(segment[2])} + sta ${segment[3].callLabel},y + """ + }, + + + + // ----------- assignment to WORD VARIABLE ---------------- + // var = wordvalue + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_VAR_WORD)) { segment -> + val number = hexVal(segment[0]) + """ + lda #<$number + ldy #>$number + sta ${segment[1].callLabel} + sty ${segment[1].callLabel}+1 + """ + }, + // var = ubytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> + when (segment[0].callLabel) { + "A" -> " sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" + "X" -> " stx ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" + "Y" -> " sty ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1" + 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 -> + """ + lda ${segment[0].callLabel} + ldy ${segment[0].callLabel}+1 + sta ${segment[1].callLabel} + sty ${segment[1].callLabel}+1 + """ + }, + // var = address-of other var + AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_VAR_WORD)) { segment -> + """ + lda #<${segment[0].callLabel} + ldy #>${segment[0].callLabel} + sta ${segment[1].callLabel} + sty ${segment[1].callLabel}+1 + """ + }, + // var = mem ubyte + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> + " lda ${hexVal(segment[0])} | 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 -> + """ + lda ${hexVal(segment[0])} + sta ${segment[1].callLabel} + lda ${hexValPlusOne(segment[0])} + sta ${segment[1].callLabel}+1 + """ + }, + // var = ubytearray[index_byte] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> + val index = hexVal(segment[0]) + " lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1" + }, + // var = ubytearray[index var] + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> + val loadA = loadAFromIndexedByVar(segment[0], segment[1]) + " $loadA | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1" + }, + // var = ubytearray[index mem] + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + 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 = intVal(segment[0]) * 2 + " lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel} | lda ${segment[1].callLabel}+${index + 1} | sta ${segment[2].callLabel}+1" + }, + // var = (u)wordarray[index var] + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> + val loadAY = loadAYFromWordIndexedByVar(segment[0], segment[1]) + """ + $loadAY + sta ${segment[2].callLabel} + sty ${segment[2].callLabel}+1 + """ + }, + // var = (u)wordarray[index mem] + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + asl a + tay + lda ${segment[1].callLabel},y + sta ${segment[2].callLabel} + lda ${segment[1].callLabel}+1,y + sta ${segment[2].callLabel}+1 + """ + }, + // mem = (u)word value + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_WORD)) { segment -> + """ + lda #<${hexVal(segment[0])} + ldy #>${hexVal(segment[0])} + sta ${hexVal(segment[1])} + sty ${hexValPlusOne(segment[1])} + """ + }, + // mem uword = ubyte var + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> + when (segment[0].callLabel) { + "A" -> " sta ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}" + "X" -> " stx ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}" + "Y" -> " sty ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}" + else -> " lda ${segment[0].callLabel} || sta ${hexVal(segment[2])} | lda #0 | sta ${hexValPlusOne(segment[2])}" + } + }, + // mem uword = mem ubyte + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${hexVal(segment[2])} + lda #0 + sta ${hexValPlusOne(segment[2])} + """ + }, + // mem uword = uword var + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> + " lda ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1 | sta ${hexVal(segment[1])} | sty ${hexValPlusOne(segment[1])}" + }, + // mem uword = address-of var + AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_MEM_WORD)) { segment -> + " lda #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} | sta ${hexVal(segment[1])} | sty ${hexValPlusOne(segment[1])}" + }, + // mem (u)word = mem (u)word + AsmPattern( + listOf(Opcode.PUSH_MEM_UW, Opcode.POP_MEM_WORD), + listOf(Opcode.PUSH_MEM_W, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + ldy ${hexValPlusOne(segment[0])} + sta ${hexVal(segment[1])} + sty ${hexValPlusOne(segment[1])} + """ + }, + // mem uword = ubytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> + val index = intVal(segment[0]) + """ + lda ${segment[1].callLabel}+$index + ldy #0 + sta ${hexVal(segment[3])} + sty ${hexValPlusOne(segment[3])} + """ + }, + // mem uword = bytearray[index] (sign extended) + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> + val index = intVal(segment[0]) + """ + lda ${segment[1].callLabel}+$index + sta ${hexVal(segment[3])} + ${signExtendA(hexValPlusOne(segment[3]))} + """ + }, + // mem uword = bytearray[index var] (sign extended) + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> + val loadA = loadAFromIndexedByVar(segment[0], segment[1]) + """ + $loadA + sta ${hexVal(segment[3])} + ${signExtendA(hexValPlusOne(segment[3]))} + """ + }, + // mem uword = bytearray[mem (u)byte] (sign extended) + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${hexVal(segment[3])} + ${signExtendA(hexValPlusOne(segment[3]))} + """ + }, + // mem uword = ubytearray[index var] + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> + val loadA = loadAFromIndexedByVar(segment[0], segment[1]) + " $loadA | sta ${hexVal(segment[3])} | lda #0 | sta ${hexValPlusOne(segment[3])}" + }, + // mem uword = ubytearray[mem (u)bute] + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${hexVal(segment[3])} + lda #0 + sta ${hexValPlusOne(segment[3])} + """ + }, + // mem uword = (u)wordarray[indexvalue] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> + val index = intVal(segment[0]) * 2 + """ + lda ${segment[1].callLabel}+$index + ldy ${segment[1].callLabel}+1+$index + sta ${hexVal(segment[2])} + sty ${hexValPlusOne(segment[2])} + """ + }, + // mem uword = (u)wordarray[index var] + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> + val loadAY = loadAYFromWordIndexedByVar(segment[0], segment[1]) + """ + $loadAY + sta ${hexVal(segment[2])} + sty ${hexValPlusOne(segment[2])} + """ + }, + // mem uword = (u)wordarray[mem index] + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + asl a + tay + lda ${segment[1].callLabel},y + sta ${hexVal(segment[2])} + lda ${segment[1].callLabel}+1,y + sta ${hexValPlusOne(segment[2])} + """ + }, + // word var = bytevar (sign extended) + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${segment[2].callLabel} + ${signExtendA(segment[2].callLabel + "+1")} + """ + }, + // mem word = bytevar (sign extended) + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${hexVal(segment[2])} + ${signExtendA(hexValPlusOne(segment[2]))} + """ + }, + // mem word = mem byte (sign extended) + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.POP_MEM_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${hexVal(segment[2])} + ${signExtendA(hexValPlusOne(segment[2]))} + """ + }, + // var = membyte (sign extended) + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${segment[2].callLabel} + ${signExtendA(segment[2].callLabel + "+1")} + """ + }, + // var = bytearray[index_byte] (sign extended) + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> + val index = hexVal(segment[0]) + """ + lda ${segment[1].callLabel}+$index + sta ${segment[3].callLabel} + ${signExtendA(segment[3].callLabel + "+1")} + """ + }, + // var = bytearray[index var] (sign extended) + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> + val loadByteA = loadAFromIndexedByVar(segment[0], segment[1]) + """ + $loadByteA + sta ${segment[3].callLabel} + ${signExtendA(segment[3].callLabel + "+1")} + """ + }, + // var = bytearray[mem (u)byte] (sign extended) + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD), + listOf(Opcode.PUSH_MEM_UB, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${segment[3].callLabel} + ${signExtendA(segment[3].callLabel + "+1")} + """ + }, + + // ----------- assignment to UWORD ARRAY ---------------- + // uwordarray[index] = (u)word value + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[1]) * 2 + val value = hexVal(segment[0]) + """ + lda #<$value + ldy #>$value + sta ${segment[2].callLabel}+$index + sty ${segment[2].callLabel}+${index + 1} + """ + }, + // uwordarray[index mem] = (u)word value + AsmPattern( + listOf(Opcode.PUSH_WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val value = hexVal(segment[0]) + """ + lda ${hexVal(segment[1])} + asl a + tay + lda #<$value + sta ${segment[2].callLabel},y + lda #>$value + sta ${segment[2].callLabel}+1,y + """ + }, + // uwordarray[index mem] = mem (u)word + AsmPattern( + listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[1])} + asl a + tay + lda ${hexVal(segment[0])} + sta ${segment[2].callLabel},y + lda ${hexValPlusOne(segment[0])} + sta ${segment[2].callLabel}+1,y + """ + }, + // uwordarray[index mem] = (u)word var + AsmPattern( + listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[1])} + asl a + tay + lda ${segment[0].callLabel} + sta ${segment[2].callLabel},y + lda ${segment[0].callLabel}+1 + sta ${segment[2].callLabel}+1,y + """ + }, + // uwordarray[index mem] = address-of var + AsmPattern( + listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[1])} + asl a + tay + lda #<${segment[0].callLabel} + sta ${segment[2].callLabel},y + lda #>${segment[0].callLabel} + sta ${segment[2].callLabel}+1,y + """ + }, + // uwordarray[index] = ubytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[2]) * 2 + when (segment[0].callLabel) { + "A" -> " sta ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index + 1}" + "X" -> " stx ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index + 1}" + "Y" -> " sty ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index + 1}" + else -> " lda ${segment[0].callLabel} | sta ${segment[3].callLabel}+$index | lda #0 | sta ${segment[3].callLabel}+${index + 1}" + } + }, + // wordarray[index] = bytevar (extend sign) + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[2]) * 2 + when (segment[0].callLabel) { + "A" -> + """ + sta ${segment[3].callLabel}+$index + ${signExtendA(segment[3].callLabel + "+${index + 1}")} + """ + "X" -> + """ + txa + sta ${segment[3].callLabel}+$index + ${signExtendA(segment[3].callLabel + "+${index + 1}")} + """ + "Y" -> + """ + tya + sta ${segment[3].callLabel}+$index + ${signExtendA(segment[3].callLabel + "+${index + 1}")} + """ + else -> + """ + lda ${segment[0].callLabel} + sta ${segment[3].callLabel}+$index + ${signExtendA(segment[3].callLabel + "+${index + 1}")} + """ + } + }, + // wordarray[index mem] = bytevar (extend sign) + AsmPattern( + listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + when (segment[0].callLabel) { + "A" -> + """ + pha + sty ${C64Zeropage.SCRATCH_B1} + lda ${hexVal(segment[2])} + asl a + tay + pla + sta ${segment[3].callLabel},y + ${signExtendA(segment[3].callLabel + "+1,y")} + """ + "X" -> + """ + stx ${C64Zeropage.SCRATCH_B1} + lda ${hexVal(segment[2])} + asl a + tay + lda ${C64Zeropage.SCRATCH_B1} + sta ${segment[3].callLabel},y + ${signExtendA(segment[3].callLabel + "+1,y")} + """ + "Y" -> + """ + sty ${C64Zeropage.SCRATCH_B1} + lda ${hexVal(segment[2])} + asl a + tay + lda ${C64Zeropage.SCRATCH_B1} + sta ${segment[3].callLabel},y + ${signExtendA(segment[3].callLabel + "+1,y")} + """ + else -> + """ + lda ${hexVal(segment[2])} + asl a + tay + lda ${segment[0].callLabel} + sta ${segment[3].callLabel},y + ${signExtendA(segment[3].callLabel + "+1,y")} + """ + } + }, + // wordarray[memory (u)byte] = ubyte mem + AsmPattern( + listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[2])} + asl a + tay + lda ${hexVal(segment[0])} + sta ${segment[3].callLabel},y + ${signExtendA(segment[3].callLabel + "+1,y")} + """ + }, + // wordarray[index] = mem byte (extend sign) + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[2]) * 2 + """ + lda ${hexVal(segment[0])} + sta ${segment[3].callLabel}+$index + ${signExtendA(segment[3].callLabel + "+${index + 1}")} + """ + }, + // wordarray2[index2] = bytearray1[index1] (extend sign) + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index1 = intVal(segment[0]) + val index2 = segment[3].arg!!.integerValue() * 2 + """ + lda ${segment[1].callLabel}+$index1 + sta ${segment[4].callLabel}+$index2 + ${signExtendA(segment[4].callLabel + "+${index2 + 1}")} + """ + }, + // wordarray2[mem (u)byte] = bytearray1[index1] (extend sign) + AsmPattern( + listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index1 = intVal(segment[0]) + """ + lda ${hexVal(segment[3])} + asl a + tay + lda ${segment[1].callLabel}+$index1 + sta ${segment[4].callLabel},y + ${signExtendA(segment[4].callLabel + "+1,y")} + """ + }, + + // wordarray[indexvar] = byte var (sign extended) + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val loadValueOnStack = when (segment[0].callLabel) { + "A" -> " pha" + "X" -> " txa | pha" + "Y" -> " tya | pha" + else -> " lda ${segment[0].callLabel} | pha" + } + val loadIndexY = when (segment[2].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[2].callLabel} | asl a | tay" + } + """ + $loadValueOnStack + $loadIndexY + pla + sta ${segment[3].callLabel},y + ${signExtendA(segment[3].callLabel + "+1,y")} + """ + }, + // wordarray[indexvar] = byte mem (sign extended) + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val loadIndexY = when (segment[2].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[2].callLabel} | asl a | tay" + } + """ + $loadIndexY + lda ${hexVal(segment[0])} + sta ${segment[3].callLabel},y + ${signExtendA(segment[3].callLabel + "+1,y")} + """ + }, + // wordarray[index] = mem word + AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[1]) * 2 + """ + lda ${hexVal(segment[0])} + sta ${segment[2].callLabel}+$index + lda ${hexValPlusOne(segment[0])} + sta ${segment[2].callLabel}+$index+1 + """ + }, + // wordarray2[indexvar] = bytearay[index] (sign extended) + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[0]) + val loadIndex2Y = when (segment[3].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[3].callLabel} | asl a | tay" + } + """ + $loadIndex2Y + lda ${segment[1].callLabel}+$index + sta ${segment[4].callLabel},y + lda ${segment[1].callLabel}+$index+1 + sta ${segment[4].callLabel}+1,y + """ + }, + // uwordarray[mem (u)byte] = mem word + AsmPattern( + listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[1])} + asl a + tay + lda ${hexVal(segment[0])} + sta ${segment[2].callLabel},y + lda ${hexValPlusOne(segment[0])} + sta ${segment[2].callLabel}+1,y + """ + }, + + // uwordarray[index mem] = ubytevar + AsmPattern( + listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + when (segment[0].callLabel) { + "A" -> + """ + pha + lda ${hexVal(segment[2])} + asl a + tay + pla + sta ${segment[3].callLabel},y + lda #0 + sta ${segment[3].callLabel}+1,y + """ + "X" -> + """ + lda ${hexVal(segment[2])} + asl a + tay + txa + sta ${segment[3].callLabel},y + lda #0 + sta ${segment[3].callLabel}+1,y + """ + "Y" -> + """ + lda ${hexVal(segment[2])} + asl a + stx ${C64Zeropage.SCRATCH_B1} + tax + tya + sta ${segment[3].callLabel},x + lda #0 + sta ${segment[3].callLabel}+1,x + ldx ${C64Zeropage.SCRATCH_B1} + """ + else -> + """ + lda ${hexVal(segment[2])} + asl a + tay + lda ${segment[0].callLabel} + sta ${segment[3].callLabel},y + lda #0 + sta ${segment[3].callLabel}+1,y + """ + } + }, + // uwordarray[index mem] = ubyte mem + AsmPattern( + listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + """ + lda ${hexVal(segment[2])} + asl a + tay + lda ${hexVal(segment[0])} + sta ${segment[3].callLabel},y + lda #0 + sta ${segment[3].callLabel}+1,y + """ + }, + // uwordarray[index] = mem ubyte + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[2]) * 2 + """ + lda ${hexVal(segment[0])} + sta ${segment[3].callLabel}+$index + lda #0 + sta ${segment[3].callLabel}+${index + 1} + """ + }, + // uwordarray[index] = (u)wordvar + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[1]) * 2 + " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}+$index | lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}+${index + 1}" + }, + // uwordarray[index] = address-of var + AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[1]) * 2 + " lda #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} | sta ${segment[2].callLabel}+$index | sty ${segment[2].callLabel}+${index + 1}" + }, + // uwordarray[index] = mem uword + AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[1]) * 2 + """ + lda ${hexVal(segment[0])} + ldy ${hexValPlusOne(segment[0])} + sta ${segment[2].callLabel}+$index + sty ${segment[2].callLabel}+${index + 1} + """ + }, + // uwordarray2[index2] = ubytearray1[index1] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index1 = intVal(segment[0]) + val index2 = segment[3].arg!!.integerValue() * 2 + """ + lda ${segment[1].callLabel}+$index1 + sta ${segment[4].callLabel}+$index2 + lda #0 + sta ${segment[4].callLabel}+${index2 + 1} + """ + }, + // uwordarray2[index2] = (u)wordarray1[index1] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index1 = intVal(segment[0]) + val index2 = intVal(segment[2]) * 2 + """ + lda ${segment[1].callLabel}+$index1 + ldy ${segment[1].callLabel}+${index1 + 1} + sta ${segment[3].callLabel}+$index2 + sta ${segment[3].callLabel}+${index2 + 1} + """ + }, + // uwordarray[indexvar] = (u)word value + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val value = hexVal(segment[0]) + val loadIndexY = when (segment[1].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[1].callLabel} | asl a | tay" + } + " $loadIndexY | lda #<$value | sta ${segment[2].callLabel},y | lda #>$value | sta ${segment[2].callLabel}+1,y" + }, + // uwordarray[indexvar] = ubyte var + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val loadValueOnStack = when (segment[0].callLabel) { + "A" -> " pha" + "X" -> " txa | pha" + "Y" -> " tya | pha" + else -> " lda ${segment[0].callLabel} | pha" + } + val loadIndexY = when (segment[2].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[2].callLabel} | asl a | tay" + } + " $loadValueOnStack | $loadIndexY | pla | sta ${segment[3].callLabel},y | lda #0 | sta ${segment[3].callLabel}+1,y" + }, + // uwordarray[indexvar] = uword var + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val loadIndexY = when (segment[1].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[1].callLabel} | asl a | tay" + } + " $loadIndexY | lda ${segment[0].callLabel} | sta ${segment[2].callLabel},y | lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}+1,y" + }, + // uwordarray[indexvar] = address-of var + AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val loadIndexY = when (segment[1].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[1].callLabel} | asl a | tay" + } + " $loadIndexY | lda #<${segment[0].callLabel} | sta ${segment[2].callLabel},y | lda #>${segment[0].callLabel} | sta ${segment[2].callLabel}+1,y" + }, + // uwordarray[indexvar] = mem ubyte + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val loadIndexY = when (segment[2].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[2].callLabel} | asl a | tay" + } + " $loadIndexY | lda ${hexVal(segment[0])} | sta ${segment[3].callLabel},y | lda #0 | sta ${segment[3].callLabel}+1,y" + }, + // uwordarray[indexvar] = mem (u)word + AsmPattern( + listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val loadIndexY = when (segment[1].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[1].callLabel} | asl a | tay" + } + " $loadIndexY | lda ${hexVal(segment[0])} | sta ${segment[2].callLabel},y | lda ${hexValPlusOne(segment[0])} | sta ${segment[2].callLabel}+1,y" + }, + // uwordarray2[indexvar] = ubytearay[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[0]) + val loadIndex2Y = when (segment[3].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[3].callLabel} | asl a | tay" + } + " $loadIndex2Y | lda ${segment[1].callLabel}+$index | sta ${segment[4].callLabel},y | lda #0 | sta ${segment[4].callLabel}+1,y" + }, + // uwordarray2[indexvar] = uwordarray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index = intVal(segment[0]) * 2 + val loadIndex2Y = when (segment[2].callLabel) { + "A" -> " asl a | tay" + "X" -> " txa | asl a | tay" + "Y" -> " tya | asl a | tay" + else -> " lda ${segment[2].callLabel} | asl a | tay" + } + " $loadIndex2Y | lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel},y | lda ${segment[1].callLabel}+${index + 1} | sta ${segment[3].callLabel}+1,y" + }, + // uwordarray2[index mem] = ubytearray1[index1] + AsmPattern( + listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_UW, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index1 = intVal(segment[0]) + """ + lda ${hexVal(segment[3])} + asl a + tay + lda ${segment[1].callLabel}+$index1 + sta ${segment[4].callLabel},y + lda #0 + sta ${segment[4].callLabel}+1,y + """ + }, + // uwordarray2[index mem] = uwordarray1[index1] + AsmPattern( + listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_MEM_B, Opcode.WRITE_INDEXED_VAR_WORD), + listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_MEM_UB, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val index1 = intVal(segment[0]) + """ + lda ${hexVal(segment[2])} + asl a + tay + lda ${segment[1].callLabel}+$index1 + sta ${segment[3].callLabel},y + lda ${segment[1].callLabel}+${index1 + 1} + sta ${segment[3].callLabel}+1,y + """ + }, + + + // ----------- assignment to FLOAT VARIABLE ---------------- + // floatvar = ubytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + val loadByteA = when (segment[0].callLabel) { + "A" -> "" + "X" -> "txa" + "Y" -> "tya" + else -> "lda ${segment[0].callLabel}" + } + """ + $loadByteA + sta ${C64Zeropage.SCRATCH_B1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.ub2float + """ + }, + // floatvar = uwordvar + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${C64Zeropage.SCRATCH_W1} + lda ${segment[0].callLabel}+1 + sta ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.uw2float + """ + }, + // floatvar = bytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + val loadByteA = when (segment[0].callLabel) { + "A" -> "" + "X" -> "txa" + "Y" -> "tya" + else -> "lda ${segment[0].callLabel}" + } + """ + $loadByteA + sta ${C64Zeropage.SCRATCH_B1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.b2float + """ + }, + // floatvar = wordvar + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${C64Zeropage.SCRATCH_W1} + lda ${segment[0].callLabel}+1 + sta ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.w2float + """ + }, + // floatvar = float value + AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> + val floatConst = getFloatConst(segment[0].arg!!) + """ + lda #<$floatConst + ldy #>$floatConst + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[1].callLabel} + ldy #>${segment[1].callLabel} + jsr c64flt.copy_float + """ + }, + // floatvar = float var + AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda #<${segment[0].callLabel} + ldy #>${segment[0].callLabel} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[1].callLabel} + ldy #>${segment[1].callLabel} + jsr c64flt.copy_float + """ + }, + // floatvar = mem float + AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda #<${hexVal(segment[0])} + ldy #>${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[1].callLabel} + ldy #>${segment[1].callLabel} + jsr c64flt.copy_float + """ + }, + // floatvar = mem byte + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_B1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.b2float + """ + }, + // floatvar = mem ubyte + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_B1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.ub2float + """ + }, + // floatvar = mem word + AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_W1} + lda ${hexValPlusOne(segment[0])} + sta ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.w2float + """ + }, + // floatvar = mem uword + AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_W1} + lda ${hexValPlusOne(segment[0])} + sta ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.uw2float + """ + }, + + // floatvar = bytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + val index = intVal(segment[0]) + """ + lda ${segment[1].callLabel}+$index + sta ${C64Zeropage.SCRATCH_B1} + lda #<${segment[3].callLabel} + ldy #>${segment[3].callLabel} + jsr c64flt.b2float + """ + }, + // floatvar = ubytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + val index = intVal(segment[0]) + """ + lda ${segment[1].callLabel}+$index + sta ${C64Zeropage.SCRATCH_B1} + lda #<${segment[3].callLabel} + ldy #>${segment[3].callLabel} + jsr c64flt.ub2float + """ + }, + // floatvar = wordarray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + val index = intVal(segment[0]) * 2 + """ + lda ${segment[1].callLabel}+$index + ldy ${segment[1].callLabel}+${index + 1} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[3].callLabel} + ldy #>${segment[3].callLabel} + jsr c64flt.w2float + """ + }, + // floatvar = uwordarray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_VAR_FLOAT)) { segment -> + val index = intVal(segment[0]) * 2 + """ + lda ${segment[1].callLabel}+$index + ldy ${segment[1].callLabel}+${index + 1} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[3].callLabel} + ldy #>${segment[3].callLabel} + jsr c64flt.uw2float + """ + }, + // floatvar = floatarray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.POP_VAR_FLOAT)) { segment -> + val index = intVal(segment[0]) * Mflpt5.MemorySize + """ + lda #<${segment[1].callLabel}+$index + ldy #>${segment[1].callLabel}+$index + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${segment[2].callLabel} + ldy #>${segment[2].callLabel} + jsr c64flt.copy_float + """ + }, + + // memfloat = float value + AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> + val floatConst = getFloatConst(segment[0].arg!!) + """ + lda #<$floatConst + ldy #>$floatConst + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[1])} + ldy #>${hexVal(segment[1])} + jsr c64flt.copy_float + """ + }, + // memfloat = float var + AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> + """ + lda #<${segment[0].callLabel} + ldy #>${segment[0].callLabel} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[1])} + ldy #>${hexVal(segment[1])} + jsr c64flt.copy_float + """ + }, + // memfloat = ubytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + val loadByteA = when (segment[0].callLabel) { + "A" -> "" + "X" -> "txa" + "Y" -> "tya" + else -> "lda ${segment[0].callLabel}" + } + """ + $loadByteA + sta ${C64Zeropage.SCRATCH_B1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.ub2float + """ + }, + // memfloat = uwordvar + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${C64Zeropage.SCRATCH_W1} + lda ${segment[0].callLabel}+1 + sta ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.uw2float + """ + }, + // memfloat = bytevar + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + val loadByteA = when (segment[0].callLabel) { + "A" -> "" + "X" -> "txa" + "Y" -> "tya" + else -> "lda ${segment[0].callLabel}" + } + """ + $loadByteA + sta ${C64Zeropage.SCRATCH_B1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.b2float + """ + }, + // memfloat = wordvar + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${C64Zeropage.SCRATCH_W1} + lda ${segment[0].callLabel}+1 + sta ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.w2float + """ + }, + // memfloat = mem byte + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_B1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.b2float + """ + }, + // memfloat = mem ubyte + AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_B1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.ub2float + """ + }, + // memfloat = mem word + AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_W1} + lda ${hexValPlusOne(segment[0])} + sta ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.w2float + """ + }, + // memfloat = mem uword + AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + """ + lda ${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_W1} + lda ${hexValPlusOne(segment[0])} + sta ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.uw2float + """ + }, + // memfloat = mem float + AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> + """ + lda #<${hexVal(segment[0])} + ldy #>${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[1])} + ldy #>${hexVal(segment[1])} + jsr c64flt.copy_float + """ + }, + // memfloat = bytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_B_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + val index = intVal(segment[0]) + """ + lda ${segment[1].callLabel}+$index + sta ${C64Zeropage.SCRATCH_B1} + lda #<${hexVal(segment[3])} + ldy #>${hexVal(segment[3])} + jsr c64flt.b2float + """ + }, + // memfloat = ubytearray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.CAST_UB_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + val index = intVal(segment[0]) + """ + lda ${segment[1].callLabel}+$index + sta ${C64Zeropage.SCRATCH_B1} + lda #<${hexVal(segment[3])} + ldy #>${hexVal(segment[3])} + jsr c64flt.ub2float + """ + }, + // memfloat = wordarray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_W_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + val index = intVal(segment[0]) * 2 + """ + lda ${segment[1].callLabel}+$index + ldy ${segment[1].callLabel}+${index + 1} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[3])} + ldy #>${hexVal(segment[3])} + jsr c64flt.w2float + """ + }, + // memfloat = uwordarray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.CAST_UW_TO_F, Opcode.POP_MEM_FLOAT)) { segment -> + val index = intVal(segment[0]) * 2 + """ + lda ${segment[1].callLabel}+$index + ldy ${segment[1].callLabel}+${index + 1} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[3])} + ldy #>${hexVal(segment[3])} + jsr c64flt.uw2float + """ + }, + // memfloat = floatarray[index] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.POP_MEM_FLOAT)) { segment -> + val index = intVal(segment[0]) * Mflpt5.MemorySize + """ + lda #<${segment[1].callLabel}+$index + ldy #>${segment[1].callLabel}+$index + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<${hexVal(segment[2])} + ldy #>${hexVal(segment[2])} + jsr c64flt.copy_float + """ + }, + // floatarray[idxbyte] = float + AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> + val floatConst = getFloatConst(segment[0].arg!!) + val index = intVal(segment[1]) * Mflpt5.MemorySize + """ + lda #<$floatConst + ldy #>$floatConst + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<(${segment[2].callLabel}+$index) + ldy #>(${segment[2].callLabel}+$index) + jsr c64flt.copy_float + """ + }, + // floatarray[idxbyte] = floatvar + AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> + val index = intVal(segment[1]) * Mflpt5.MemorySize + """ + lda #<${segment[0].callLabel} + ldy #>${segment[0].callLabel} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<(${segment[2].callLabel}+$index) + ldy #>(${segment[2].callLabel}+$index) + jsr c64flt.copy_float + """ + }, + // floatarray[idxbyte] = memfloat + AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> + val index = intVal(segment[1]) * Mflpt5.MemorySize + """ + lda #<${hexVal(segment[0])} + ldy #>${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<(${segment[2].callLabel}+$index) + ldy #>(${segment[2].callLabel}+$index) + jsr c64flt.copy_float + """ + }, + // floatarray[idx2] = floatarray[idx1] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> + val index1 = intVal(segment[0]) * Mflpt5.MemorySize + val index2 = intVal(segment[2]) * Mflpt5.MemorySize + """ + lda #<(${segment[1].callLabel}+$index1) + ldy #>(${segment[1].callLabel}+$index1) + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1 + 1} + lda #<(${segment[3].callLabel}+$index2) + ldy #>(${segment[3].callLabel}+$index2) + jsr c64flt.copy_float + """ + }, + + // ---------- some special operations ------------------ + // var word = AX register pair + AsmPattern(listOf(Opcode.PUSH_REGAX_WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + sta ${segment[1].callLabel} + stx ${segment[1].callLabel}+1 + """ + }, + // var word = AY register pair + AsmPattern(listOf(Opcode.PUSH_REGAY_WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + sta ${segment[1].callLabel} + sty ${segment[1].callLabel}+1 + """ + }, + // var word = XY register pair + AsmPattern(listOf(Opcode.PUSH_REGXY_WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + stx ${segment[1].callLabel} + sty ${segment[1].callLabel}+1 + """ + }, + // mem word = AX register pair + AsmPattern(listOf(Opcode.PUSH_REGAX_WORD, Opcode.POP_MEM_WORD)) { segment -> + """ + sta ${hexVal(segment[1])} + stx ${hexValPlusOne(segment[1])} + """ + }, + // mem word = AY register pair + AsmPattern(listOf(Opcode.PUSH_REGAY_WORD, Opcode.POP_MEM_WORD)) { segment -> + """ + sta ${hexVal(segment[1])} + sty ${hexValPlusOne(segment[1])} + """ + }, + // mem word = XY register pair + AsmPattern(listOf(Opcode.PUSH_REGXY_WORD, Opcode.POP_MEM_WORD)) { segment -> + """ + stx ${hexVal(segment[1])} + sty ${hexValPlusOne(segment[1])} + """ + }, + + // AX register pair = word value + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGAX_WORD)) { segment -> + val value = hexVal(segment[0]) + " lda #<$value | ldx #>$value" + }, + // AY register pair = word value + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGAY_WORD)) { segment -> + val value = hexVal(segment[0]) + " lda #<$value | ldy #>$value" + }, + // XY register pair = word value + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGXY_WORD)) { segment -> + val value = hexVal(segment[0]) + " ldx #<$value | ldy #>$value" + }, + // AX register pair = word var + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGAX_WORD)) { segment -> + " lda ${segment[0].callLabel} | ldx ${segment[0].callLabel}+1" + }, + // AY register pair = word var + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGAY_WORD)) { segment -> + " lda ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1" + }, + // XY register pair = word var + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGXY_WORD)) { segment -> + " ldx ${segment[0].callLabel} | ldy ${segment[0].callLabel}+1" + }, + // AX register pair = mem word + AsmPattern( + listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGAX_WORD), + listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGAX_WORD)) { segment -> + " lda ${hexVal(segment[0])} | ldx ${hexValPlusOne(segment[0])}" + }, + // AY register pair = mem word + AsmPattern( + listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGAY_WORD), + listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGAY_WORD)) { segment -> + " lda ${hexVal(segment[0])} | ldy ${hexValPlusOne(segment[0])}" + }, + // XY register pair = mem word + AsmPattern( + listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGXY_WORD), + listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGXY_WORD)) { segment -> + " ldx ${hexVal(segment[0])} | ldy ${hexValPlusOne(segment[0])}" + }, + + + // byte var = wordvar as (u)byte + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_UB, Opcode.POP_VAR_BYTE), + listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_B, Opcode.POP_VAR_BYTE)) { segment -> + when (segment[2].callLabel) { + "A" -> " lda ${segment[0].callLabel}" + "X" -> " ldx ${segment[0].callLabel}" + "Y" -> " ldy ${segment[0].callLabel}" + else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}" + } + }, + // byte var = uwordvar as (u)byte + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_UB, Opcode.POP_VAR_BYTE), + listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_B, Opcode.POP_VAR_BYTE)) { segment -> + when (segment[2].callLabel) { + "A" -> " lda ${segment[0].callLabel}" + "X" -> " ldx ${segment[0].callLabel}" + "Y" -> " ldy ${segment[0].callLabel}" + else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel}" + } + }, + // byte var = msb(word var) + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.MSB, Opcode.POP_VAR_BYTE)) { segment -> + when (segment[2].callLabel) { + "A" -> " lda ${segment[0].callLabel}+1" + "X" -> " ldx ${segment[0].callLabel}+1" + "Y" -> " ldy ${segment[0].callLabel}+1" + else -> " lda ${segment[0].callLabel}+1 | sta ${segment[2].callLabel}" + } + }, + // push word var as (u)byte + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_UB), + listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_W_TO_B)) { segment -> + " lda ${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex " + }, + // push uword var as (u)byte + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_UB), + listOf(Opcode.PUSH_VAR_WORD, Opcode.CAST_UW_TO_B)) { segment -> + " lda ${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex " + }, + // push msb(word var) + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.MSB)) { segment -> + " lda ${segment[0].callLabel}+1 | sta ${ESTACK_LO.toHex()},x | dex " + }, + + // set a register pair to a certain memory address (of a variable) + AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGAX_WORD)) { segment -> + " lda #<${segment[0].callLabel} | ldx #>${segment[0].callLabel} " + }, + AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGAY_WORD)) { segment -> + " lda #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} " + }, + AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGXY_WORD)) { segment -> + " ldx #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} " + }, + + // push memory byte | bytevalue + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE)) { segment -> + " lda ${hexVal(segment[0])} | ora #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + }, + // push memory byte & bytevalue + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE)) { segment -> + " lda ${hexVal(segment[0])} | and #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + }, + // push memory byte ^ bytevalue + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment -> + " lda ${hexVal(segment[0])} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + }, + // push var byte | bytevalue + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE)) { segment -> + " lda ${segment[0].callLabel} | ora #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + }, + // push var byte & bytevalue + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE)) { segment -> + " lda ${segment[0].callLabel} | and #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + }, + // push var byte ^ bytevalue + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment -> + " lda ${segment[0].callLabel} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex " + }, + + // push memory word | wordvalue + AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITOR_WORD), + listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITOR_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + ora #<${hexVal(segment[1])} + sta ${ESTACK_LO.toHex()},x + lda ${hexValPlusOne(segment[0])} + ora #>${hexVal(segment[1])} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + // push memory word & wordvalue + AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITAND_WORD), + listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITAND_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + and #<${hexVal(segment[1])} + sta ${ESTACK_LO.toHex()},x + lda ${hexValPlusOne(segment[0])} + and #>${hexVal(segment[1])} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + // push memory word ^ wordvalue + AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITXOR_WORD), + listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITXOR_WORD)) { segment -> + """ + lda ${hexVal(segment[0])} + eor #<${hexVal(segment[1])} + sta ${ESTACK_LO.toHex()},x + lda ${hexValPlusOne(segment[0])} + eor #>${hexVal(segment[1])} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + // push var word | wordvalue + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITOR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + ora #<${hexVal(segment[1])} + sta ${ESTACK_LO.toHex()},x + lda ${segment[0].callLabel}+1 + ora #>${hexVal(segment[1])} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + // push var word & wordvalue + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITAND_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + and #<${hexVal(segment[1])} + sta ${ESTACK_LO.toHex()},x + lda ${segment[0].callLabel}+1 + and #>${hexVal(segment[1])} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + // push var word ^ wordvalue + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITXOR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + eor #<${hexVal(segment[1])} + sta ${ESTACK_LO.toHex()},x + lda ${segment[0].callLabel}+1 + eor #>${hexVal(segment[1])} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + // push var byte & var byte + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITAND_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + """ + lda ${segment[0].callLabel} + and ${segment[1].callLabel} + sta ${segment[3].callLabel} + """ + }, + // push var byte | var byte + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITOR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + """ + lda ${segment[0].callLabel} + ora ${segment[1].callLabel} + sta ${segment[3].callLabel} + """ + }, + // push var byte ^ var byte + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITXOR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + """ + lda ${segment[0].callLabel} + eor ${segment[1].callLabel} + sta ${segment[3].callLabel} + """ + }, + // push var word & var word + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITAND_WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + and ${segment[1].callLabel} + sta ${segment[3].callLabel} + lda ${segment[0].callLabel}+1 + and ${segment[1].callLabel}+1 + sta ${segment[3].callLabel}+1 + """ + }, + // push var word | var word + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITOR_WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + ora ${segment[1].callLabel} + sta ${segment[3].callLabel} + lda ${segment[0].callLabel}+1 + ora ${segment[1].callLabel}+1 + sta ${segment[3].callLabel}+1 + """ + }, + // push var word ^ var word + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITXOR_WORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + eor ${segment[1].callLabel} + sta ${segment[3].callLabel} + lda ${segment[0].callLabel}+1 + eor ${segment[1].callLabel}+1 + sta ${segment[3].callLabel}+1 + """ + }, + + // bytearray[consti3] = bytearray[consti1] ^ bytearray[consti2] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, + Opcode.BITXOR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val i1 = segment[5].arg!!.integerValue() + val i2 = segment[0].arg!!.integerValue() + val i3 = segment[2].arg!!.integerValue() + """ + lda ${segment[1].callLabel}+$i2 + eor ${segment[3].callLabel}+$i3 + sta ${segment[6].callLabel}+$i1 + """ + }, + // warray[consti3] = warray[consti1] ^ warray[consti2] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, + Opcode.BITXOR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val i1 = segment[5].arg!!.integerValue() * 2 + val i2 = segment[0].arg!!.integerValue() * 2 + val i3 = segment[2].arg!!.integerValue() * 2 + """ + lda ${segment[1].callLabel}+$i2 + eor ${segment[3].callLabel}+$i3 + sta ${segment[6].callLabel}+$i1 + lda ${segment[1].callLabel}+${i2 + 1} + eor ${segment[3].callLabel}+${i3 + 1} + sta ${segment[6].callLabel}+${i1 + 1} + """ + }, + + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${ESTACK_LO.toHex()},x + lda ${segment[1].callLabel} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment -> + """ + lda #${hexVal(segment[0])} + sta ${ESTACK_LO.toHex()},x + lda ${segment[1].callLabel} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.MKWORD)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${ESTACK_LO.toHex()},x + lda #${hexVal(segment[1])} + sta ${ESTACK_HI.toHex()},x + dex + """ + }, + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${segment[3].callLabel} + lda ${segment[1].callLabel} + sta ${segment[3].callLabel}+1 + """ + }, + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.MKWORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${segment[3].callLabel} + lda #${hexVal(segment[1])} + sta ${segment[3].callLabel}+1 + """ + }, + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD, Opcode.POP_VAR_WORD)) { segment -> + """ + lda #${hexVal(segment[0])} + sta ${segment[3].callLabel} + lda ${segment[1].callLabel} + sta ${segment[3].callLabel}+1 + """ + }, + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD, Opcode.CAST_UW_TO_W, Opcode.POP_VAR_WORD)) { segment -> + """ + lda ${segment[0].callLabel} + sta ${segment[4].callLabel} + lda ${segment[1].callLabel} + sta ${segment[4].callLabel}+1 + """ + }, + + // more efficient versions of x+1 and x-1 to avoid pushing the 1 on the stack + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.ADD_B), listOf(Opcode.PUSH_BYTE, Opcode.ADD_UB)) { segment -> + val amount = segment[0].arg!!.integerValue() + if (amount in 1..2) { + " inc ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) + } else + null + }, + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.ADD_UW), listOf(Opcode.PUSH_WORD, Opcode.ADD_W)) { segment -> + val amount = segment[0].arg!!.integerValue() + if (amount in 1..2) { + " inc ${(ESTACK_LO + 1).toHex()},x | bne + | inc ${(ESTACK_HI + 1).toHex()},x |+ | ".repeat(amount) + } else + null + }, + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.SUB_B), listOf(Opcode.PUSH_BYTE, Opcode.SUB_UB)) { segment -> + val amount = segment[0].arg!!.integerValue() + if (amount in 1..2) { + " dec ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) + } else + null + }, + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.SUB_UW), listOf(Opcode.PUSH_WORD, Opcode.SUB_W)) { segment -> + val amount = segment[0].arg!!.integerValue() + if (amount in 1..2) { + " lda ${(ESTACK_LO + 1).toHex()},x | bne + | dec ${(ESTACK_HI + 1).toHex()},x |+ | dec ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) + } else + null + }, + + // @todo optimize 8 and 16 bit adds and subs (avoid stack use altogether on most common operations) + + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.CMP_B), listOf(Opcode.PUSH_VAR_BYTE, Opcode.CMP_UB)) { segment -> + // this pattern is encountered as part of the loop bound condition in for loops (var + cmp + jz/jnz) + val cmpval = segment[1].arg!!.integerValue() + " lda ${segment[0].callLabel} | cmp #$cmpval " + }, + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.CMP_W), listOf(Opcode.PUSH_VAR_WORD, Opcode.CMP_UW)) { segment -> + // this pattern is encountered as part of the loop bound condition in for loops (var + cmp + jz/jnz) + """ + lda ${segment[0].callLabel} + cmp #<${hexVal(segment[1])} + bne + + lda ${segment[0].callLabel}+1 + cmp #>${hexVal(segment[1])} + bne + + lda #0 ++ + """ + }, + + AsmPattern(listOf(Opcode.RRESTOREX, Opcode.LINE, Opcode.RSAVEX), listOf(Opcode.RRESTOREX, Opcode.RSAVEX)) { segment -> + """ + sta ${C64Zeropage.SCRATCH_REG} + pla + tax + pha + lda ${C64Zeropage.SCRATCH_REG} + """ + }, + + // various optimizable integer multiplications + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.MUL_B), listOf(Opcode.PUSH_BYTE, Opcode.MUL_UB)) { segment -> + val amount = segment[0].arg!!.integerValue() + val result = optimizedIntMultiplicationsOnStack(segment[1], amount) + result ?: " lda #${hexVal(segment[0])} | sta ${ESTACK_LO.toHex()},x | dex | jsr prog8_lib.mul_byte" + }, + AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.MUL_W), listOf(Opcode.PUSH_WORD, Opcode.MUL_UW)) { segment -> + val amount = segment[0].arg!!.integerValue() + val result = optimizedIntMultiplicationsOnStack(segment[1], amount) + if (result != null) result else { + val value = hexVal(segment[0]) + " lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex | jsr prog8_lib.mul_word" + } + }, + + // various variable or memory swaps + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.POP_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment -> + val var1 = segment[0].callLabel + val var2 = segment[1].callLabel + val var3 = segment[2].callLabel + val var4 = segment[3].callLabel + if (var1 == var3 && var2 == var4) { + """ + lda $var1 + tay + lda $var2 + sta $var1 + sty $var2 + """ + } else null + }, + AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.POP_VAR_WORD, Opcode.POP_VAR_WORD)) { segment -> + val var1 = segment[0].callLabel + val var2 = segment[1].callLabel + val var3 = segment[2].callLabel + val var4 = segment[3].callLabel + if (var1 == var3 && var2 == var4) { + """ + lda $var1 + tay + lda $var2 + sta $var1 + sty $var2 + lda $var1+1 + tay + lda $var2+1 + sta $var1+1 + sty $var2+1 + """ + } else null + }, + AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_B, Opcode.POP_MEM_BYTE, Opcode.POP_MEM_BYTE), + listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_MEM_UB, Opcode.POP_MEM_BYTE, Opcode.POP_MEM_BYTE)) { segment -> + val addr1 = segment[0].arg!!.integerValue() + val addr2 = segment[1].arg!!.integerValue() + val addr3 = segment[2].arg!!.integerValue() + val addr4 = segment[3].arg!!.integerValue() + if (addr1 == addr3 && addr2 == addr4) { + """ + lda ${addr1.toHex()} + tay + lda ${addr2.toHex()} + sta ${addr1.toHex()} + sty ${addr2.toHex()} + """ + } else null + }, + AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_W, Opcode.POP_MEM_WORD, Opcode.POP_MEM_WORD), + listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_MEM_UW, Opcode.POP_MEM_WORD, Opcode.POP_MEM_WORD)) { segment -> + val addr1 = segment[0].arg!!.integerValue() + val addr2 = segment[1].arg!!.integerValue() + val addr3 = segment[2].arg!!.integerValue() + val addr4 = segment[3].arg!!.integerValue() + if (addr1 == addr3 && addr2 == addr4) { + """ + lda ${addr1.toHex()} + tay + lda ${addr2.toHex()} + sta ${addr1.toHex()} + sty ${addr2.toHex()} + lda ${(addr1 + 1).toHex()} + tay + lda ${(addr2 + 1).toHex()} + sta ${(addr1 + 1).toHex()} + sty ${(addr2 + 1).toHex()} + """ + } else null + }, + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, + Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val i1 = segment[0].arg!!.integerValue() + val i2 = segment[2].arg!!.integerValue() + val i3 = segment[4].arg!!.integerValue() + val i4 = segment[6].arg!!.integerValue() + val array1 = segment[1].callLabel + val array2 = segment[3].callLabel + val array3 = segment[5].callLabel + val array4 = segment[7].callLabel + if (i1 == i3 && i2 == i4 && array1 == array3 && array2 == array4) { + """ + lda $array1+$i1 + tay + lda $array2+$i2 + sta $array1+$i1 + sty $array2+$i2 + """ + } else null + }, + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_BYTE, + Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment -> + val vi1 = segment[0].callLabel + val vi2 = segment[2].callLabel + val vi3 = segment[4].callLabel + val vi4 = segment[6].callLabel + val array1 = segment[1].callLabel + val array2 = segment[3].callLabel + val array3 = segment[5].callLabel + val array4 = segment[7].callLabel + if (vi1 == vi3 && vi2 == vi4 && array1 == array3 && array2 == array4) { + val load1 = loadAFromIndexedByVar(segment[0], segment[1]) + val load2 = loadAFromIndexedByVar(segment[2], segment[3]) + val storeIn1 = storeAToIndexedByVar(segment[0], segment[1]) + val storeIn2 = storeAToIndexedByVar(segment[2], segment[3]) + """ + $load1 + pha + $load2 + $storeIn1 + pla + $storeIn2 + """ + } else null + }, + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, + Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val i1 = segment[0].arg!!.integerValue() * 2 + val i2 = segment[2].arg!!.integerValue() * 2 + val i3 = segment[4].arg!!.integerValue() * 2 + val i4 = segment[6].arg!!.integerValue() * 2 + val array1 = segment[1].callLabel + val array2 = segment[3].callLabel + val array3 = segment[5].callLabel + val array4 = segment[7].callLabel + if (i1 == i3 && i2 == i4 && array1 == array3 && array2 == array4) { + """ + lda $array1+$i1 + tay + lda $array2+$i2 + sta $array1+$i1 + sty $array2+$i2 + lda $array1+${i1 + 1} + tay + lda $array2+${i2 + 1} + sta $array1+${i1 + 1} + sty $array2+${i2 + 1} + """ + } else null + }, + AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, + Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.PUSH_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment -> + val vi1 = segment[0].callLabel + val vi2 = segment[2].callLabel + val vi3 = segment[4].callLabel + val vi4 = segment[6].callLabel + val array1 = segment[1].callLabel + val array2 = segment[3].callLabel + val array3 = segment[5].callLabel + val array4 = segment[7].callLabel + if (vi1 == vi3 && vi2 == vi4 && array1 == array3 && array2 == array4) { + // SCRATCH_B1 = index1 + // SCRATCH_REG = index2 + // SCRATCH_W1 = temp storage of array[index2] + """ + lda ${segment[0].callLabel} + asl a + sta ${C64Zeropage.SCRATCH_B1} + lda ${segment[2].callLabel} + asl a + sta ${C64Zeropage.SCRATCH_REG} + stx ${C64Zeropage.SCRATCH_REG_X} + tax + lda ${segment[3].callLabel},x + ldy ${segment[3].callLabel}+1,x + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1}+1 + ldx ${C64Zeropage.SCRATCH_B1} + lda ${segment[1].callLabel},x + ldy ${segment[1].callLabel}+1,x + ldx ${C64Zeropage.SCRATCH_REG} + sta ${segment[3].callLabel},x + tya + sta ${segment[3].callLabel}+1,x + ldx ${C64Zeropage.SCRATCH_B1} + lda ${C64Zeropage.SCRATCH_W1} + sta ${segment[1].callLabel},x + lda ${C64Zeropage.SCRATCH_W1}+1 + sta ${segment[1].callLabel}+1,x + ldx ${C64Zeropage.SCRATCH_REG_X} + """ + } else null + } + +) diff --git a/compiler/src/prog8/compiler/target/c64/SimpleAsm.kt b/compiler/src/prog8/compiler/target/c64/SimpleAsm.kt new file mode 100644 index 000000000..e6e058c99 --- /dev/null +++ b/compiler/src/prog8/compiler/target/c64/SimpleAsm.kt @@ -0,0 +1,531 @@ +package prog8.compiler.target.c64 + +import prog8.compiler.CompilerException +import prog8.compiler.intermediate.Instruction +import prog8.compiler.intermediate.IntermediateProgram +import prog8.compiler.intermediate.LabelInstr +import prog8.compiler.intermediate.Opcode +import prog8.compiler.toHex +import prog8.vm.stackvm.Syscall +import prog8.vm.stackvm.syscallsForStackVm + + +private var breakpointCounter = 0 + +internal fun simpleInstr2Asm(ins: Instruction, block: IntermediateProgram.ProgramBlock): String? { + // a label 'instruction' is simply translated into a asm label + if(ins is LabelInstr) { + val labelresult = + if(ins.name.startsWith("${block.name}.")) + ins.name.substring(block.name.length+1) + else + ins.name + return if(ins.asmProc) labelresult+"\t\t.proc" else labelresult + } + + // simple opcodes that are translated directly into one or a few asm instructions + return when(ins.opcode) { + Opcode.LINE -> " ;\tsrc line: ${ins.callLabel}" + Opcode.NOP -> " nop" // shouldn't be present anymore though + Opcode.START_PROCDEF -> "" // is done as part of a label + Opcode.END_PROCDEF -> " .pend" + Opcode.TERMINATE -> " brk" + Opcode.SEC -> " sec" + Opcode.CLC -> " clc" + Opcode.SEI -> " sei" + Opcode.CLI -> " cli" + Opcode.CARRY_TO_A -> " lda #0 | adc #0" + Opcode.JUMP -> { + if(ins.callLabel!=null) + " jmp ${ins.callLabel}" + else + " jmp ${hexVal(ins)}" + } + Opcode.CALL -> { + if(ins.callLabel!=null) + " jsr ${ins.callLabel}" + else + " jsr ${hexVal(ins)}" + } + Opcode.RETURN -> " rts" + Opcode.RSAVE -> { + // save cpu status flag and all registers A, X, Y. + // see http://6502.org/tutorials/register_preservation.html + " php | sta ${C64Zeropage.SCRATCH_REG} | pha | txa | pha | tya | pha | lda ${C64Zeropage.SCRATCH_REG}" + } + Opcode.RRESTORE -> { + // restore all registers and cpu status flag + " pla | tay | pla | tax | pla | plp" + } + Opcode.RSAVEX -> " sta ${C64Zeropage.SCRATCH_REG} | txa | pha | lda ${C64Zeropage.SCRATCH_REG}" + Opcode.RRESTOREX -> " sta ${C64Zeropage.SCRATCH_REG} | pla | tax | lda ${C64Zeropage.SCRATCH_REG}" + Opcode.DISCARD_BYTE -> " inx" + Opcode.DISCARD_WORD -> " inx" + Opcode.DUP_B -> { + " dex | lda ${(ESTACK_LO+1).toHex()},x | sta ${ESTACK_LO.toHex()},x" + } + Opcode.DUP_W -> { + " dex | lda ${(ESTACK_LO+1).toHex()},x | sta ${ESTACK_LO.toHex()},x | lda ${(ESTACK_HI+1).toHex()},x | sta ${ESTACK_HI.toHex()},x " + } + Opcode.DISCARD_FLOAT -> " inx | inx | inx" + Opcode.INLINE_ASSEMBLY -> "@inline@" + (ins.callLabel2 ?: "") // All of the inline assembly is stored in the calllabel2 property. the '@inline@' is a special marker to accept it. + Opcode.INCLUDE_FILE -> { + val offset = if(ins.arg==null) "" else ", ${ins.arg.integerValue()}" + val length = if(ins.arg2==null) "" else ", ${ins.arg2.integerValue()}" + " .binary \"${ins.callLabel}\" $offset $length" + } + Opcode.SYSCALL -> { + if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr }) + throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}") + val call = Syscall.values().find { it.callNr==ins.arg.numericValue() } + when(call) { + Syscall.FUNC_SIN, + Syscall.FUNC_COS, + Syscall.FUNC_ABS, + Syscall.FUNC_TAN, + Syscall.FUNC_ATAN, + Syscall.FUNC_LN, + Syscall.FUNC_LOG2, + Syscall.FUNC_SQRT, + Syscall.FUNC_RAD, + Syscall.FUNC_DEG, + Syscall.FUNC_ROUND, + Syscall.FUNC_FLOOR, + Syscall.FUNC_CEIL, + Syscall.FUNC_RNDF, + Syscall.FUNC_ANY_F, + Syscall.FUNC_ALL_F, + Syscall.FUNC_MAX_F, + Syscall.FUNC_MIN_F, + Syscall.FUNC_SUM_F -> " jsr c64flt.${call.name.toLowerCase()}" + null -> "" + else -> " jsr prog8_lib.${call.name.toLowerCase()}" + } + } + Opcode.BREAKPOINT -> { + breakpointCounter++ + "_prog8_breakpoint_$breakpointCounter\tnop" + } + + Opcode.PUSH_BYTE -> { + " lda #${hexVal(ins)} | sta ${ESTACK_LO.toHex()},x | dex" + } + Opcode.PUSH_WORD -> { + val value = hexVal(ins) + " lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex" + } + Opcode.PUSH_FLOAT -> { + val floatConst = getFloatConst(ins.arg!!) + " lda #<$floatConst | ldy #>$floatConst | jsr c64flt.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. You should probably not use the X register (or only in trivial assignments)") + "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 -> { + " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda ${ins.callLabel}+1 | sta ${ESTACK_HI.toHex()},x | dex" + } + Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr c64flt.push_float" + Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> { + """ + lda ${hexVal(ins)} + sta ${ESTACK_LO.toHex()},x + dex + """ + } + Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> { + """ + lda ${hexVal(ins)} + sta ${ESTACK_LO.toHex()},x + lda ${hexValPlusOne(ins)} + sta ${ESTACK_HI.toHex()},x + dex + """ + } + Opcode.PUSH_MEM_FLOAT -> { + " lda #<${hexVal(ins)} | ldy #>${hexVal(ins)}| jsr c64flt.push_float" + } + Opcode.PUSH_MEMREAD -> { + """ + lda ${(ESTACK_LO+1).toHex()},x + sta (+) +1 + lda ${(ESTACK_HI+1).toHex()},x + sta (+) +2 ++ lda 65535 ; modified + sta ${(ESTACK_LO+1).toHex()},x + """ + } + + Opcode.PUSH_REGAY_WORD -> { + " sta ${ESTACK_LO.toHex()},x | tya | sta ${ESTACK_HI.toHex()},x | dex " + } + Opcode.PUSH_ADDR_HEAPVAR -> { + " lda #<${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda #>${ins.callLabel} | sta ${ESTACK_HI.toHex()},x | dex" + } + Opcode.POP_REGAX_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") + Opcode.POP_REGXY_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") + Opcode.POP_REGAY_WORD -> { + " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x " + } + + Opcode.READ_INDEXED_VAR_BYTE -> { + """ + ldy ${(ESTACK_LO+1).toHex()},x + lda ${ins.callLabel},y + sta ${(ESTACK_LO+1).toHex()},x + """ + } + Opcode.READ_INDEXED_VAR_WORD -> { + """ + lda ${(ESTACK_LO+1).toHex()},x + asl a + tay + lda ${ins.callLabel},y + sta ${(ESTACK_LO+1).toHex()},x + lda ${ins.callLabel}+1,y + sta ${(ESTACK_HI+1).toHex()},x + """ + } + Opcode.READ_INDEXED_VAR_FLOAT -> { + """ + lda #<${ins.callLabel} + ldy #>${ins.callLabel} + jsr c64flt.push_float_from_indexed_var + """ + } + Opcode.WRITE_INDEXED_VAR_BYTE -> { + """ + inx + ldy ${ESTACK_LO.toHex()},x + inx + lda ${ESTACK_LO.toHex()},x + sta ${ins.callLabel},y + """ + } + Opcode.WRITE_INDEXED_VAR_WORD -> { + """ + inx + lda ${ESTACK_LO.toHex()},x + asl a + tay + inx + lda ${ESTACK_LO.toHex()},x + sta ${ins.callLabel},y + lda ${ESTACK_HI.toHex()},x + sta ${ins.callLabel}+1,y + """ + } + Opcode.WRITE_INDEXED_VAR_FLOAT -> { + """ + lda #<${ins.callLabel} + ldy #>${ins.callLabel} + jsr c64flt.pop_float_to_indexed_var + """ + } + Opcode.POP_MEM_BYTE -> { + """ + inx + lda ${ESTACK_LO.toHex()},x + sta ${hexVal(ins)} + """ + } + Opcode.POP_MEM_WORD -> { + """ + inx + lda ${ESTACK_LO.toHex()},x + sta ${hexVal(ins)} + lda ${ESTACK_HI.toHex()},x + sta ${hexValPlusOne(ins)} + """ + } + Opcode.POP_MEM_FLOAT -> { + " lda ${hexVal(ins)} | ldy ${hexValPlusOne(ins)} | jsr c64flt.pop_float" + } + Opcode.POP_MEMWRITE -> { + """ + inx + lda ${ESTACK_LO.toHex()},x + sta (+) +1 + lda ${ESTACK_HI.toHex()},x + sta (+) +2 + inx + lda ${ESTACK_LO.toHex()},x ++ sta 65535 ; modified + """ + } + + Opcode.POP_VAR_BYTE -> { + when (ins.callLabel) { + "X" -> throw CompilerException("makes no sense to pop X, it's used as a stack pointer itself") + "A" -> " inx | lda ${ESTACK_LO.toHex()},x" + "Y" -> " inx | ldy ${ESTACK_LO.toHex()},x" + else -> " inx | lda ${ESTACK_LO.toHex()},x | sta ${ins.callLabel}" + } + } + Opcode.POP_VAR_WORD -> { + " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x | sta ${ins.callLabel} | sty ${ins.callLabel}+1" + } + Opcode.POP_VAR_FLOAT -> { + " lda #<${ins.callLabel} | ldy #>${ins.callLabel} | jsr c64flt.pop_float" + } + + Opcode.INC_VAR_UB, Opcode.INC_VAR_B -> { + when (ins.callLabel) { + "A" -> " clc | adc #1" + "X" -> " inx" + "Y" -> " iny" + else -> " inc ${ins.callLabel}" + } + } + Opcode.INC_VAR_UW, Opcode.INC_VAR_W -> { + " inc ${ins.callLabel} | bne + | inc ${ins.callLabel}+1 |+" + } + Opcode.INC_VAR_F -> { + """ + lda #<${ins.callLabel} + ldy #>${ins.callLabel} + jsr c64flt.inc_var_f + """ + } + Opcode.POP_INC_MEMORY -> { + """ + inx + lda ${ESTACK_LO.toHex()},x + sta (+) +1 + lda ${ESTACK_HI.toHex()},x + sta (+) +2 ++ inc 65535 ; modified + """ + } + Opcode.POP_DEC_MEMORY -> { + """ + inx + lda ${ESTACK_LO.toHex()},x + sta (+) +1 + lda ${ESTACK_HI.toHex()},x + sta (+) +2 ++ dec 65535 ; modified + """ + } + Opcode.DEC_VAR_UB, Opcode.DEC_VAR_B -> { + when (ins.callLabel) { + "A" -> " sec | sbc #1" + "X" -> " dex" + "Y" -> " dey" + else -> " dec ${ins.callLabel}" + } + } + Opcode.DEC_VAR_UW, Opcode.DEC_VAR_W -> { + " lda ${ins.callLabel} | bne + | dec ${ins.callLabel}+1 |+ | dec ${ins.callLabel}" + } + Opcode.DEC_VAR_F -> { + """ + lda #<${ins.callLabel} + ldy #>${ins.callLabel} + jsr c64flt.dec_var_f + """ + } + Opcode.INC_MEMORY -> " inc ${hexVal(ins)}" + Opcode.DEC_MEMORY -> " dec ${hexVal(ins)}" + Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> " inx | txa | pha | lda ${ESTACK_LO.toHex()},x | tax | inc ${ins.callLabel},x | pla | tax" + Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> " inx | txa | pha | lda ${ESTACK_LO.toHex()},x | tax | dec ${ins.callLabel},x | pla | tax" + + Opcode.NEG_B -> " jsr prog8_lib.neg_b" + Opcode.NEG_W -> " jsr prog8_lib.neg_w" + Opcode.NEG_F -> " jsr c64flt.neg_f" + Opcode.ABS_B -> " jsr prog8_lib.abs_b" + Opcode.ABS_W -> " jsr prog8_lib.abs_w" + Opcode.ABS_F -> " jsr c64flt.abs_f" + Opcode.POW_F -> " jsr c64flt.pow_f" + Opcode.INV_BYTE -> { + """ + lda ${(ESTACK_LO + 1).toHex()},x + eor #255 + sta ${(ESTACK_LO + 1).toHex()},x + """ + } + Opcode.INV_WORD -> " jsr prog8_lib.inv_word" + Opcode.NOT_BYTE -> " jsr prog8_lib.not_byte" + Opcode.NOT_WORD -> " jsr prog8_lib.not_word" + Opcode.BCS -> { + val label = ins.callLabel ?: hexVal(ins) + " bcs $label" + } + Opcode.BCC -> { + val label = ins.callLabel ?: hexVal(ins) + " bcc $label" + } + Opcode.BNEG -> { + val label = ins.callLabel ?: hexVal(ins) + " bmi $label" + } + Opcode.BPOS -> { + val label = ins.callLabel ?: hexVal(ins) + " bpl $label" + } + Opcode.BVC -> { + val label = ins.callLabel ?: hexVal(ins) + " bvc $label" + } + Opcode.BVS -> { + val label = ins.callLabel ?: hexVal(ins) + " bvs $label" + } + Opcode.BZ -> { + val label = ins.callLabel ?: hexVal(ins) + " beq $label" + } + Opcode.BNZ -> { + val label = ins.callLabel ?: hexVal(ins) + " bne $label" + } + Opcode.JZ -> { + val label = ins.callLabel ?: hexVal(ins) + """ + inx + lda ${(ESTACK_LO).toHex()},x + beq $label + """ + } + Opcode.JZW -> { + val label = ins.callLabel ?: hexVal(ins) + """ + inx + lda ${(ESTACK_LO).toHex()},x + beq $label + lda ${(ESTACK_HI).toHex()},x + beq $label + """ + } + Opcode.JNZ -> { + val label = ins.callLabel ?: hexVal(ins) + """ + inx + lda ${(ESTACK_LO).toHex()},x + bne $label + """ + } + Opcode.JNZW -> { + val label = ins.callLabel ?: hexVal(ins) + """ + inx + lda ${(ESTACK_LO).toHex()},x + bne $label + lda ${(ESTACK_HI).toHex()},x + bne $label + """ + } + Opcode.CAST_B_TO_UB -> "" // is a no-op, just carry on with the byte as-is + Opcode.CAST_UB_TO_B -> "" // is a no-op, just carry on with the byte as-is + Opcode.CAST_W_TO_UW -> "" // is a no-op, just carry on with the word as-is + Opcode.CAST_UW_TO_W -> "" // is a no-op, just carry on with the word as-is + Opcode.CAST_W_TO_UB -> "" // is a no-op, just carry on with the lsb of the word as-is + Opcode.CAST_W_TO_B -> "" // is a no-op, just carry on with the lsb of the word as-is + Opcode.CAST_UW_TO_UB -> "" // is a no-op, just carry on with the lsb of the uword as-is + Opcode.CAST_UW_TO_B -> "" // is a no-op, just carry on with the lsb of the uword as-is + Opcode.CAST_UB_TO_F -> " jsr c64flt.stack_ub2float" + Opcode.CAST_B_TO_F -> " jsr c64flt.stack_b2float" + Opcode.CAST_UW_TO_F -> " jsr c64flt.stack_uw2float" + Opcode.CAST_W_TO_F -> " jsr c64flt.stack_w2float" + Opcode.CAST_F_TO_UB -> " jsr c64flt.stack_float2uw" + Opcode.CAST_F_TO_B -> " jsr c64flt.stack_float2w" + Opcode.CAST_F_TO_UW -> " jsr c64flt.stack_float2uw" + Opcode.CAST_F_TO_W -> " jsr c64flt.stack_float2w" + Opcode.CAST_UB_TO_UW, Opcode.CAST_UB_TO_W -> " lda #0 | sta ${(ESTACK_HI+1).toHex()},x" // clear the msb + Opcode.CAST_B_TO_UW, Opcode.CAST_B_TO_W -> " lda ${(ESTACK_LO+1).toHex()},x | ${signExtendA("${(ESTACK_HI+1).toHex()},x")}" // sign extend the lsb + Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x" + Opcode.MKWORD -> " inx | lda ${ESTACK_LO.toHex()},x | sta ${(ESTACK_HI+1).toHex()},x " + + Opcode.ADD_UB, Opcode.ADD_B -> { // TODO inline better (pattern with more opcodes) + """ + lda ${(ESTACK_LO + 2).toHex()},x + clc + adc ${(ESTACK_LO + 1).toHex()},x + inx + sta ${(ESTACK_LO + 1).toHex()},x + """ + } + Opcode.SUB_UB, Opcode.SUB_B -> { // TODO inline better (pattern with more opcodes) + """ + lda ${(ESTACK_LO + 2).toHex()},x + sec + sbc ${(ESTACK_LO + 1).toHex()},x + inx + sta ${(ESTACK_LO + 1).toHex()},x + """ + } + Opcode.ADD_W, Opcode.ADD_UW -> " jsr prog8_lib.add_w" + Opcode.SUB_W, Opcode.SUB_UW -> " jsr prog8_lib.sub_w" + Opcode.MUL_B, Opcode.MUL_UB -> " jsr prog8_lib.mul_byte" + Opcode.MUL_W, Opcode.MUL_UW -> " jsr prog8_lib.mul_word" + Opcode.MUL_F -> " jsr c64flt.mul_f" + Opcode.ADD_F -> " jsr c64flt.add_f" + Opcode.SUB_F -> " jsr c64flt.sub_f" + Opcode.DIV_F -> " jsr c64flt.div_f" + Opcode.IDIV_UB -> " jsr prog8_lib.idiv_ub" + Opcode.IDIV_B -> " jsr prog8_lib.idiv_b" + Opcode.IDIV_W -> " jsr prog8_lib.idiv_w" + Opcode.IDIV_UW -> " jsr prog8_lib.idiv_uw" + + Opcode.AND_BYTE -> " jsr prog8_lib.and_b" + Opcode.OR_BYTE -> " jsr prog8_lib.or_b" + Opcode.XOR_BYTE -> " jsr prog8_lib.xor_b" + Opcode.AND_WORD -> " jsr prog8_lib.and_w" + Opcode.OR_WORD -> " jsr prog8_lib.or_w" + Opcode.XOR_WORD -> " jsr prog8_lib.xor_w" + + Opcode.BITAND_BYTE -> " jsr prog8_lib.bitand_b" + Opcode.BITOR_BYTE -> " jsr prog8_lib.bitor_b" + Opcode.BITXOR_BYTE -> " jsr prog8_lib.bitxor_b" + Opcode.BITAND_WORD -> " jsr prog8_lib.bitand_w" + Opcode.BITOR_WORD -> " jsr prog8_lib.bitor_w" + Opcode.BITXOR_WORD -> " jsr prog8_lib.bitxor_w" + + Opcode.REMAINDER_UB -> " jsr prog8_lib.remainder_ub" + Opcode.REMAINDER_UW -> " jsr prog8_lib.remainder_uw" + + Opcode.GREATER_B -> " jsr prog8_lib.greater_b" + Opcode.GREATER_UB -> " jsr prog8_lib.greater_ub" + Opcode.GREATER_W -> " jsr prog8_lib.greater_w" + Opcode.GREATER_UW -> " jsr prog8_lib.greater_uw" + Opcode.GREATER_F -> " jsr c64flt.greater_f" + + Opcode.GREATEREQ_B -> " jsr prog8_lib.greatereq_b" + Opcode.GREATEREQ_UB -> " jsr prog8_lib.greatereq_ub" + Opcode.GREATEREQ_W -> " jsr prog8_lib.greatereq_w" + Opcode.GREATEREQ_UW -> " jsr prog8_lib.greatereq_uw" + Opcode.GREATEREQ_F -> " jsr c64flt.greatereq_f" + + Opcode.EQUAL_BYTE -> " jsr prog8_lib.equal_b" + Opcode.EQUAL_WORD -> " jsr prog8_lib.equal_w" + Opcode.EQUAL_F -> " jsr c64flt.equal_f" + Opcode.NOTEQUAL_BYTE -> " jsr prog8_lib.notequal_b" + Opcode.NOTEQUAL_WORD -> " jsr prog8_lib.notequal_w" + Opcode.NOTEQUAL_F -> " jsr c64flt.notequal_f" + + Opcode.LESS_UB -> " jsr prog8_lib.less_ub" + Opcode.LESS_B -> " jsr prog8_lib.less_b" + Opcode.LESS_UW -> " jsr prog8_lib.less_uw" + Opcode.LESS_W -> " jsr prog8_lib.less_w" + Opcode.LESS_F -> " jsr c64flt.less_f" + + Opcode.LESSEQ_UB -> " jsr prog8_lib.lesseq_ub" + Opcode.LESSEQ_B -> " jsr prog8_lib.lesseq_b" + Opcode.LESSEQ_UW -> " jsr prog8_lib.lesseq_uw" + Opcode.LESSEQ_W -> " jsr prog8_lib.lesseq_w" + Opcode.LESSEQ_F -> " jsr c64flt.lesseq_f" + + Opcode.SHIFTEDL_BYTE -> " asl ${(ESTACK_LO+1).toHex()},x" + Opcode.SHIFTEDL_WORD -> " asl ${(ESTACK_LO+1).toHex()},x | rol ${(ESTACK_HI+1).toHex()},x" + Opcode.SHIFTEDR_SBYTE -> " lda ${(ESTACK_LO+1).toHex()},x | asl a | ror ${(ESTACK_LO+1).toHex()},x" + Opcode.SHIFTEDR_UBYTE -> " lsr ${(ESTACK_LO+1).toHex()},x" + Opcode.SHIFTEDR_SWORD -> " lda ${(ESTACK_HI+1).toHex()},x | asl a | ror ${(ESTACK_HI+1).toHex()},x | ror ${(ESTACK_LO+1).toHex()},x" + Opcode.SHIFTEDR_UWORD -> " lsr ${(ESTACK_HI+1).toHex()},x | ror ${(ESTACK_LO+1).toHex()},x" + + else -> null + } +}