diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index a1af4e217..af5487811 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -1206,7 +1206,12 @@ $label nop""") internal fun signExtendStackLsb(valueDt: DataType) { // sign extend signed byte on stack to signed word on stack when(valueDt) { - DataType.UBYTE -> out(" lda #0 | sta P8ESTACK_HI+1,x") + DataType.UBYTE -> { + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + out(" stz P8ESTACK_HI+1,x") + else + out(" lda #0 | sta P8ESTACK_HI+1,x") + } DataType.BYTE -> out(" jsr prog8_lib.sign_extend_stack_byte") else -> throw AssemblyError("need byte type") } @@ -1216,7 +1221,10 @@ $label nop""") // sign extend signed byte in a var to a full word in that variable when(valueDt) { DataType.UBYTE -> { - out(" lda #0 | sta $asmvar+1") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + out(" stz $asmvar+1") + else + out(" lda #0 | sta $asmvar+1") } DataType.BYTE -> { out(""" diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 98b2004af..03e9bc4aa 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -1110,21 +1110,28 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen val sourceName = asmgen.asmVariableName(bytevar) when(wordtarget.kind) { TargetStorageKind.VARIABLE -> { - asmgen.out(""" - lda $sourceName - sta ${wordtarget.asmVarname} - lda #0 - sta ${wordtarget.asmVarname}+1 - """) + asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz ${wordtarget.asmVarname}+1") + else + asmgen.out(" lda #0 | sta ${wordtarget.asmVarname}+1") } TargetStorageKind.ARRAY -> { if (wordtarget.constArrayIndexValue!=null) { val scaledIdx = wordtarget.constArrayIndexValue!! * 2 - asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}+$scaledIdx | lda #0 | sta ${wordtarget.asmVarname}+$scaledIdx+1") + asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}+$scaledIdx") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz ${wordtarget.asmVarname}+$scaledIdx+1") + else + asmgen.out(" lda #0 | sta ${wordtarget.asmVarname}+$scaledIdx+1") } else { asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array!!, wordtarget.datatype, CpuRegister.Y) - asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname},y | lda #0 | iny | sta ${wordtarget.asmVarname},y") + asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname},y | iny") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz ${wordtarget.asmVarname},y") + else + asmgen.out(" lda #0 | sta ${wordtarget.asmVarname},y") } } TargetStorageKind.REGISTER -> { @@ -1136,12 +1143,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } TargetStorageKind.STACK -> { - asmgen.out(""" - lda $sourceName - sta P8ESTACK_LO,x - lda #0 - sta P8ESTACK_HI,x - dex""") + asmgen.out(" lda $sourceName | sta P8ESTACK_LO,x") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz P8ESTACK_HI,x | dex") + else + asmgen.out(" lda #0 | sta P8ESTACK_HI,x | dex") } else -> throw AssemblyError("target type isn't word") } @@ -1392,14 +1398,23 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen TargetStorageKind.ARRAY -> { if (target.array!!.indexer.indexNum!=null) { val indexValue = target.array.indexer.constIndex()!! * DataType.FLOAT.memorySize() - asmgen.out(""" - lda #0 - sta ${target.asmVarname}+$indexValue - sta ${target.asmVarname}+$indexValue+1 - sta ${target.asmVarname}+$indexValue+2 - sta ${target.asmVarname}+$indexValue+3 - sta ${target.asmVarname}+$indexValue+4 - """) + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(""" + stz ${target.asmVarname}+$indexValue + stz ${target.asmVarname}+$indexValue+1 + stz ${target.asmVarname}+$indexValue+2 + stz ${target.asmVarname}+$indexValue+3 + stz ${target.asmVarname}+$indexValue+4 + """) + else + asmgen.out(""" + lda #0 + sta ${target.asmVarname}+$indexValue + sta ${target.asmVarname}+$indexValue+1 + sta ${target.asmVarname}+$indexValue+2 + sta ${target.asmVarname}+$indexValue+3 + sta ${target.asmVarname}+$indexValue+4 + """) } else { val asmvarname = asmgen.asmVariableName(target.array.indexer.indexVar!!) asmgen.out(""" @@ -1561,12 +1576,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen if (address != null) { when(wordtarget.kind) { TargetStorageKind.VARIABLE -> { - asmgen.out(""" - lda ${address.toHex()} - sta ${wordtarget.asmVarname} - lda #0 - sta ${wordtarget.asmVarname}+1 - """) + asmgen.out(" lda ${address.toHex()} | sta ${wordtarget.asmVarname}") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz ${wordtarget.asmVarname}+1") + else + asmgen.out(" lda #0 | sta ${wordtarget.asmVarname}+1") } TargetStorageKind.ARRAY -> { throw AssemblyError("no asm gen for assign memory byte at $address to array ${wordtarget.asmVarname}") @@ -1578,12 +1592,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen else -> throw AssemblyError("word regs can only be pair") } TargetStorageKind.STACK -> { - asmgen.out(""" - lda ${address.toHex()} - sta P8ESTACK_LO,x - lda #0 - sta P8ESTACK_HI,x - dex""") + asmgen.out(" lda ${address.toHex()} | sta P8ESTACK_LO,x") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz P8ESTACK_HI,x | dex") + else + asmgen.out(" lda #0 | sta P8ESTACK_HI,x | dex") } else -> throw AssemblyError("other types aren't word") } @@ -1591,7 +1604,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen when(wordtarget.kind) { TargetStorageKind.VARIABLE -> { asmgen.loadByteFromPointerIntoA(identifier) - asmgen.out(" sta ${wordtarget.asmVarname} | lda #0 | sta ${wordtarget.asmVarname}+1") + asmgen.out(" sta ${wordtarget.asmVarname}") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz ${wordtarget.asmVarname}+1") + else + asmgen.out(" lda #0 | sta ${wordtarget.asmVarname}+1") } TargetStorageKind.ARRAY -> { throw AssemblyError("no asm gen for assign memory byte $identifier to array ${wordtarget.asmVarname} ") @@ -1607,7 +1624,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } TargetStorageKind.STACK -> { asmgen.loadByteFromPointerIntoA(identifier) - asmgen.out(" sta P8ESTACK_LO,x | lda #0 | sta P8ESTACK_HI,x | dex") + asmgen.out(" sta P8ESTACK_LO,x") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz P8ESTACK_HI,x | dex") + else + asmgen.out(" lda #0 | sta P8ESTACK_HI,x | dex") } else -> throw AssemblyError("other types aren't word") } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt index e1969d748..3a348bcdc 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -643,14 +643,24 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sta $name""") } "<<" -> { - if(value>=8) asmgen.out(" lda #0 | sta $name") - else repeat(value) { asmgen.out(" asl $name") } + if(value>=8) { + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz $name") + else + asmgen.out(" lda #0 | sta $name") + } + else repeat(value) { asmgen.out(" asl $name") } } ">>" -> { if(value>0) { if (dt == DataType.UBYTE) { - if(value>=8) asmgen.out(" lda #0 | sta $name") - else repeat(value) { asmgen.out(" lsr $name") } + if(value>=8) { + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz $name") + else + asmgen.out(" lda #0 | sta $name") + } + else repeat(value) { asmgen.out(" lsr $name") } } else { when { value>=8 -> asmgen.out(""" @@ -665,7 +675,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, ldy #$value jsr math.lsr_byte_A sta $name""") - else -> repeat(value) { asmgen.out(" lda $name | asl a | ror $name") } + else -> repeat(value) { asmgen.out(" lda $name | asl a | ror $name") } } } } @@ -858,8 +868,19 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } "<<" -> { when { - value>=16 -> asmgen.out(" lda #0 | sta $name | sta $name+1") - value==8 -> asmgen.out(" lda $name | sta $name+1 | lda #0 | sta $name") + value>=16 -> { + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz $name | stz $name+1") + else + asmgen.out(" lda #0 | sta $name | sta $name+1") + } + value==8 -> { + asmgen.out(" lda $name | sta $name+1") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz $name") + else + asmgen.out(" lda #0 | sta $name") + } value>2 -> asmgen.out(""" ldy #$value - asl $name @@ -874,8 +895,19 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, if (value > 0) { if(dt==DataType.UWORD) { when { - value>=16 -> asmgen.out(" lda #0 | sta $name | sta $name+1") - value==8 -> asmgen.out(" lda $name+1 | sta $name | lda #0 | sta $name+1") + value>=16 -> { + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz $name | stz $name+1") + else + asmgen.out(" lda #0 | sta $name | sta $name+1") + } + value==8 -> { + asmgen.out(" lda $name+1 | sta $name") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz $name+1") + else + asmgen.out(" lda #0 | sta $name+1") + } value>2 -> asmgen.out(""" ldy #$value - lsr $name+1 @@ -921,41 +953,41 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, when { value == 0 -> { if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) - asmgen.out(" stz $name | stz $name+1") + asmgen.out(" stz $name | stz $name+1") else - asmgen.out(" lda #0 | sta $name | sta $name+1") + asmgen.out(" lda #0 | sta $name | sta $name+1") } value and 255 == 0 -> { if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) - asmgen.out(" stz $name") + asmgen.out(" stz $name") else - asmgen.out(" lda #0 | sta $name") - asmgen.out(" lda $name+1 | and #>$value | sta $name+1") + asmgen.out(" lda #0 | sta $name") + asmgen.out(" lda $name+1 | and #>$value | sta $name+1") } value < 0x0100 -> { - asmgen.out(" lda $name | and #$value | sta $name") + asmgen.out(" lda $name | and #$value | sta $name") if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) asmgen.out(" stz $name+1") else asmgen.out(" lda #0 | sta $name+1") } - else -> asmgen.out(" lda $name | and #<$value | sta $name | lda $name+1 | and #>$value | sta $name+1") + else -> asmgen.out(" lda $name | and #<$value | sta $name | lda $name+1 | and #>$value | sta $name+1") } } "^" -> { when { value == 0 -> {} - value and 255 == 0 -> asmgen.out(" lda $name+1 | eor #>$value | sta $name+1") - value < 0x0100 -> asmgen.out(" lda $name | eor #$value | sta $name") - else -> asmgen.out(" lda $name | eor #<$value | sta $name | lda $name+1 | eor #>$value | sta $name+1") + value and 255 == 0 -> asmgen.out(" lda $name+1 | eor #>$value | sta $name+1") + value < 0x0100 -> asmgen.out(" lda $name | eor #$value | sta $name") + else -> asmgen.out(" lda $name | eor #<$value | sta $name | lda $name+1 | eor #>$value | sta $name+1") } } "|" -> { when { value == 0 -> {} - value and 255 == 0 -> asmgen.out(" lda $name+1 | ora #>$value | sta $name+1") - value < 0x0100 -> asmgen.out(" lda $name | ora #$value | sta $name") - else -> asmgen.out(" lda $name | ora #<$value | sta $name | lda $name+1 | ora #>$value | sta $name+1") + value and 255 == 0 -> asmgen.out(" lda $name+1 | ora #>$value | sta $name+1") + value < 0x0100 -> asmgen.out(" lda $name | ora #$value | sta $name") + else -> asmgen.out(" lda $name | ora #<$value | sta $name | lda $name+1 | ora #>$value | sta $name+1") } } else -> throw AssemblyError("invalid operator for in-place modification $operator") @@ -1019,11 +1051,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sta $name+1""") } "*" -> { + asmgen.out(" lda $otherName | sta P8ZP_SCRATCH_W1") + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz P8ZP_SCRATCH_W1+1") + else + asmgen.out(" lda #0 | sta P8ZP_SCRATCH_W1+1") asmgen.out(""" - lda $otherName - sta P8ZP_SCRATCH_W1 - lda #0 - sta P8ZP_SCRATCH_W1+1 lda $name ldy $name+1 jsr math.multiply_words @@ -1068,12 +1101,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } "&" -> { - asmgen.out(" lda $otherName | and $name | sta $name") - if(dt in WordDatatypes) - asmgen.out(" lda #0 | sta $name+1") + asmgen.out(" lda $otherName | and $name | sta $name") + if(dt in WordDatatypes) { + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz $name+1") + else + asmgen.out(" lda #0 | sta $name+1") + } } - "^" -> asmgen.out(" lda $otherName | eor $name | sta $name") - "|" -> asmgen.out(" lda $otherName | ora $name | sta $name") + "^" -> asmgen.out(" lda $otherName | eor $name | sta $name") + "|" -> asmgen.out(" lda $otherName | ora $name | sta $name") else -> throw AssemblyError("invalid operator for in-place modification $operator") } } @@ -1081,8 +1118,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, // the value is a proper 16-bit word, so use both bytes of it. when (operator) { // note: ** (power) operator requires floats. - "+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name | lda $name+1 | adc $otherName+1 | sta $name+1") - "-" -> asmgen.out(" lda $name | sec | sbc $otherName | sta $name | lda $name+1 | sbc $otherName+1 | sta $name+1") + "+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name | lda $name+1 | adc $otherName+1 | sta $name+1") + "-" -> asmgen.out(" lda $name | sec | sbc $otherName | sta $name | lda $name+1 | sbc $otherName+1 | sta $name+1") "*" -> { asmgen.out(""" lda $otherName @@ -1322,8 +1359,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, "&" -> { asmgen.assignExpressionToRegister(value, RegisterOrPair.A) asmgen.out(" and $name | sta $name") - if(dt in WordDatatypes) - asmgen.out(" lda #0 | sta $name+1") + if(dt in WordDatatypes) { + if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) + asmgen.out(" stz $name+1") + else + asmgen.out(" lda #0 | sta $name+1") + } } "^" -> { asmgen.assignExpressionToRegister(value, RegisterOrPair.A) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index fa1108b6b..2bc492e6f 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,7 +2,6 @@ TODO ==== -- use 'stz' more on cx16 when setting variables to zero or clearing a word's msb etc. - see if we can group some errors together for instance the (now single) errors about unidentified symbols - Cx16 target: support full-screen 640x480 and 320x240 graphics? That requires our own custom graphics routines though to draw lines. - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' diff --git a/examples/test.p8 b/examples/test.p8 index 11a9cb9b2..ddd2aa14e 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,7 +9,7 @@ main { ubyte ub1 ubyte ub2 - uw = ub1 as uword + ub2 ; fairly ok asm (TODO make it use stz on cx16) + uw = ub1 as uword + ub2 ; fairly ok asm.. but the next though...: ub1++ uw = ub1 + ub2 ; TODO horrible asm using the eval stack... fix