diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index f4038449b..04fe630c0 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -22,27 +22,20 @@ sub start() { - c64scr.print(" X=") - c64scr.print_ub(X) - c64.CHROUT('\n') +; c64scr.print(" X=") +; c64scr.print_ub(X) +; c64.CHROUT('\n') - c64scr.print(" X=") - c64scr.print_ub(X) - c64.CHROUT('\n') + ubyte[256] screenarray + ubyte index = 2 + screenarray[1]-- + screenarray[index]-- + + +; c64scr.print(" X=") +; c64scr.print_ub(X) +; c64.CHROUT('\n') } } - -~ irq { - -sub irq() { - memory ubyte[256] screenarray = $0400 - memory ubyte firstscreenchar = $0400 - - screenarray[0]++ ; @todo incorrect code generated? - firstscreenchar++ ; ... this is okay - c64.EXTCOL++ -} - -} diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index e710ce065..55c78dbf5 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -342,6 +342,28 @@ private class StatementTranslator(private val prog: IntermediateProgram, } } + private fun opcodeIncArrayindexedVar(dt: DataType): Opcode { + return when(dt) { + DataType.ARRAY_UB -> Opcode.INC_INDEXED_VAR_UB + DataType.ARRAY_B -> Opcode.INC_INDEXED_VAR_B + DataType.ARRAY_UW -> Opcode.INC_INDEXED_VAR_UW + DataType.ARRAY_W -> Opcode.INC_INDEXED_VAR_W + DataType.ARRAY_F -> Opcode.INC_INDEXED_VAR_FLOAT + else -> throw CompilerException("can't inc type $dt") + } + } + + private fun opcodeDecArrayindexedVar(dt: DataType): Opcode { + return when(dt) { + DataType.ARRAY_UB -> Opcode.DEC_INDEXED_VAR_UB + DataType.ARRAY_B -> Opcode.DEC_INDEXED_VAR_B + DataType.ARRAY_UW -> Opcode.DEC_INDEXED_VAR_UW + DataType.ARRAY_W -> Opcode.DEC_INDEXED_VAR_W + DataType.ARRAY_F -> Opcode.DEC_INDEXED_VAR_FLOAT + else -> throw CompilerException("can't dec type $dt") + } + } + private fun translate(stmt: InlineAssembly) { prog.instr(Opcode.INLINE_ASSEMBLY, callLabel = stmt.assembly) } @@ -573,7 +595,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, DataType.ARRAY_B, DataType.ARRAY_W -> { if(lv.heapId==null) throw CompilerException("array should have been moved into heap ${lv.position}") - prog.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId)) + prog.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId)) // XXX push address of array } } } @@ -634,7 +656,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, DataType.UWORD -> prog.instr(Opcode.PUSH_MEM_UW, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!)) DataType.WORD -> prog.instr(Opcode.PUSH_MEM_W, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!)) DataType.FLOAT -> prog.instr(Opcode.PUSH_MEM_FLOAT, Value(DataType.UWORD, (target.value as LiteralValue).asNumericValue!!)) - else -> TODO("invalid datatype for memory variable expression: $target") + else -> throw CompilerException("invalid datatype for memory variable expression: $target") } } } @@ -1213,16 +1235,12 @@ private class StatementTranslator(private val prog: IntermediateProgram, } } stmt.target.arrayindexed!=null -> { - // todo: generate more efficient bytecode for this? - translate(stmt.target.arrayindexed!!, false) - val one = Value(stmt.target.arrayindexed!!.resultingDatatype(namespace, heap)!!, 1) - val opcode = opcodePush(one.type) - prog.instr(opcode, one) + val variable = stmt.target.arrayindexed!!.identifier?.targetStatement(namespace) as VarDecl + translate(stmt.target.arrayindexed!!.arrayspec.x) when(stmt.operator) { - "++" -> prog.instr(opcodeAdd(one.type)) - "--" -> prog.instr(opcodeSub(one.type)) + "++" -> prog.instr(opcodeIncArrayindexedVar(variable.datatype), callLabel = variable.scopedname) + "--" -> prog.instr(opcodeDecArrayindexedVar(variable.datatype), callLabel = variable.scopedname) } - translate(stmt.target.arrayindexed!!, true) } else -> throw CompilerException("very strange postincrdecr") } diff --git a/compiler/src/prog8/compiler/intermediate/Opcode.kt b/compiler/src/prog8/compiler/intermediate/Opcode.kt index 2dae39c1e..4aa070c18 100644 --- a/compiler/src/prog8/compiler/intermediate/Opcode.kt +++ b/compiler/src/prog8/compiler/intermediate/Opcode.kt @@ -192,13 +192,23 @@ enum class Opcode { NOTEQUAL_WORD, NOTEQUAL_F, - // arrayspec access + // array access and simple manipulations READ_INDEXED_VAR_BYTE, READ_INDEXED_VAR_WORD, READ_INDEXED_VAR_FLOAT, WRITE_INDEXED_VAR_BYTE, WRITE_INDEXED_VAR_WORD, WRITE_INDEXED_VAR_FLOAT, + INC_INDEXED_VAR_B, + INC_INDEXED_VAR_UB, + INC_INDEXED_VAR_W, + INC_INDEXED_VAR_UW, + INC_INDEXED_VAR_FLOAT, + DEC_INDEXED_VAR_B, + DEC_INDEXED_VAR_UB, + DEC_INDEXED_VAR_W, + DEC_INDEXED_VAR_UW, + DEC_INDEXED_VAR_FLOAT, // branching, without consuming a value from the stack JUMP, @@ -248,5 +258,9 @@ val opcodesWithVarArgument = setOf( Opcode.POP_VAR_BYTE, Opcode.POP_VAR_WORD, Opcode.POP_VAR_FLOAT, Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_FLOAT, Opcode.PUSH_ADDR_HEAPVAR, Opcode.READ_INDEXED_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.READ_INDEXED_VAR_FLOAT, - Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.WRITE_INDEXED_VAR_FLOAT + Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.WRITE_INDEXED_VAR_FLOAT, + Opcode.INC_INDEXED_VAR_UB, Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UW, + Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_FLOAT, + Opcode.DEC_INDEXED_VAR_UB, Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UW, + Opcode.DEC_INDEXED_VAR_W, Opcode.DEC_INDEXED_VAR_FLOAT ) diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index b72ae0150..dcc3d1e37 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -808,6 +808,26 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } } } + else if((opcodes[0]==Opcode.PUSH_BYTE && opcodes[1] in setOf(Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB, + Opcode.INC_INDEXED_VAR_UW, Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_FLOAT, + Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB, Opcode.DEC_INDEXED_VAR_W, + Opcode.DEC_INDEXED_VAR_UW, Opcode.DEC_INDEXED_VAR_FLOAT))) { + val fragment = sameConstantIndexedVarOperation(segment[1].callLabel!!, segment[0].arg!!.integerValue(), segment[1]) + if(fragment!=null) { + fragment.segmentSize=2 + result.add(fragment) + } + } + else if((opcodes[0]==Opcode.PUSH_VAR_BYTE && opcodes[1] in setOf(Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB, + Opcode.INC_INDEXED_VAR_UW, Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_FLOAT, + Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB, Opcode.DEC_INDEXED_VAR_W, + Opcode.DEC_INDEXED_VAR_UW, Opcode.DEC_INDEXED_VAR_FLOAT))) { + val fragment = sameIndexedVarOperation(segment[1].callLabel!!, segment[0].callLabel!!, segment[1]) + if(fragment!=null) { + fragment.segmentSize=2 + result.add(fragment) + } + } else if((opcodes[0]==Opcode.PUSH_MEM_UB && opcodes[2]==Opcode.POP_MEM_BYTE) || (opcodes[0]==Opcode.PUSH_MEM_B && opcodes[2]==Opcode.POP_MEM_BYTE) || (opcodes[0]==Opcode.PUSH_MEM_UW && opcodes[2]==Opcode.POP_MEM_WORD) || @@ -877,6 +897,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.ROR2_BYTE -> AsmFragment(" lda $variable+$index | lsr a | bcc + | ora #\$80 |+ | sta $variable+$index", 10) Opcode.ROL2_WORD -> AsmFragment(" asl $variable+$index | rol $variable+${index+1} | bcc + | inc $variable+$index |+",20) Opcode.ROR2_WORD -> AsmFragment(" lsr $variable+${index+1} | ror $variable+$index | bcc + | lda $variable+${index+1} | ora #\$80 | sta $variable+${index+1} |+", 30) + Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" inc $variable+$index", 2) + Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" dec $variable+$index", 5) + Opcode.INC_INDEXED_VAR_W -> TODO("inc array_w") + Opcode.INC_INDEXED_VAR_UW -> TODO("inc array_uw") + Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f") + Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w") + Opcode.DEC_INDEXED_VAR_UW -> TODO("dec array_uw") + Opcode.DEC_INDEXED_VAR_FLOAT -> TODO("dec array_f") else -> null } } @@ -921,6 +949,15 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.ROR2_BYTE -> AsmFragment("$saveX $loadX lda $variable,x | lsr a | bcc + | ora #\$80 |+ | sta $variable,x $restoreX", 10) Opcode.ROL2_WORD -> AsmFragment(" txa | $loadXWord asl $variable,x | rol $variable+1,x | bcc + | inc $variable,x |+ | tax", 30) Opcode.ROR2_WORD -> AsmFragment("$saveX $loadXWord lsr $variable+1,x | ror $variable,x | bcc + | lda $variable+1,x | ora #\$80 | sta $variable+1,x |+ $restoreX", 30) + Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX inc $variable,x | tax", 10) + Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX dec $variable,x | tax", 10) + Opcode.INC_INDEXED_VAR_W -> TODO("inc array_w") + Opcode.INC_INDEXED_VAR_UW -> TODO("inc array_uw") + Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f") + Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w") + Opcode.DEC_INDEXED_VAR_UW -> TODO("dec array_uw") + Opcode.DEC_INDEXED_VAR_FLOAT -> TODO("dec array_f") + else -> null } } @@ -2807,7 +2844,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, 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 " } - ) } diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index 642eb217a..faf845b69 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -944,6 +944,18 @@ class StackVm(private var traceOutputFile: String?) { checkDt(variable, DataType.FLOAT) variables[ins.callLabel] =variable.dec() } + Opcode.INC_INDEXED_VAR_B,Opcode.INC_INDEXED_VAR_UB,Opcode.INC_INDEXED_VAR_W,Opcode.INC_INDEXED_VAR_UW,Opcode.INC_INDEXED_VAR_FLOAT -> { + val index = evalstack.pop().integerValue() + val variable = getVar(ins.callLabel!!) + val array = heap.get(variable.heapId) + array.array!![index].inc() + } + Opcode.DEC_INDEXED_VAR_B,Opcode.DEC_INDEXED_VAR_UB,Opcode.DEC_INDEXED_VAR_W,Opcode.DEC_INDEXED_VAR_UW,Opcode.DEC_INDEXED_VAR_FLOAT -> { + val index = evalstack.pop().integerValue() + val variable = getVar(ins.callLabel!!) + val array = heap.get(variable.heapId) + array.array!![index].dec() + } Opcode.MSB -> { val v = evalstack.pop() checkDt(v, DataType.UWORD, DataType.WORD)