diff --git a/codeCore/src/prog8/code/ast/AstStatements.kt b/codeCore/src/prog8/code/ast/AstStatements.kt index d8b6990f9..22b527bf6 100644 --- a/codeCore/src/prog8/code/ast/AstStatements.kt +++ b/codeCore/src/prog8/code/ast/AstStatements.kt @@ -59,7 +59,7 @@ sealed interface IPtAssignment { get() = children.size>2 } -class PtAssignment(position: Position) : PtNode(position), IPtAssignment +class PtAssignment(position: Position, val isVarInitializer: Boolean=false) : PtNode(position), IPtAssignment class PtAugmentedAssign(val operator: String, position: Position) : PtNode(position), IPtAssignment diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 6603c8064..9c29c1059 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -21,6 +21,8 @@ internal class AssignmentAsmGen( private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen, allocator) fun translate(assignment: PtAssignment) { +// if(assignment.isVarInitializer) +// println("VARINIT ${assignment.target} ${assignment.value}") val target = AsmAssignTarget.fromAstAssignment(assignment.target, assignment.definingISub(), asmgen) val source = AsmAssignSource.fromAstSource(assignment.value, program, asmgen).adjustSignedUnsigned(target) val pos = if(assignment.position !== Position.DUMMY) assignment.position else if(assignment.target.position !== Position.DUMMY) assignment.target.position else assignment.value.position diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index e3908b90c..d6bbca0f4 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -46,7 +46,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express normalsub.returns.zip(assignmentTargets).zip(registersReverseOrder).forEach { val target = it.first.second as PtAssignTarget if(!target.void) { - val assignSingle = PtAssignment(assignment.position) + val assignSingle = PtAssignment(assignment.position, assignment.isVarInitializer) assignSingle.add(target) assignSingle.add(PtIdentifier("cx16.${it.second.toString().lowercase()}", it.first.first, assignment.position)) result += translateRegularAssign(assignSingle) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 6fc754b08..6ef4de0ed 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -1764,11 +1764,9 @@ class IRCodeGen( for ((value, register) in ret.children.zip(registersReverseOrder)) { val tr = expressionEval.translateExpression(value as PtExpression) addToResult(result, tr, tr.resultReg, -1) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.STOREM, tr.dt, reg1=tr.resultReg, labelSymbol = "cx16.${register.toString().lowercase()}") - it += IRInstruction(Opcode.RETURN) - } + addInstr(result, IRInstruction(Opcode.STOREM, tr.dt, reg1=tr.resultReg, labelSymbol = "cx16.${register.toString().lowercase()}"), null) } + addInstr(result, IRInstruction(Opcode.RETURN), null) return result } diff --git a/compiler/res/prog8lib/c128/syslib.p8 b/compiler/res/prog8lib/c128/syslib.p8 index 3fd00edac..b96d56d8a 100644 --- a/compiler/res/prog8lib/c128/syslib.p8 +++ b/compiler/res/prog8lib/c128/syslib.p8 @@ -585,7 +585,7 @@ _setup_raster_irq ora #%10000000 sta c64.SCROLY ; set most significant bit of raster position + lda #%00000001 - sta c64.IREQMASK ;enable raster interrupt signals from vic + sta c64.IREQMASK ; enable raster interrupt signals from vic rts }} } diff --git a/compiler/res/prog8lib/c64/syslib.p8 b/compiler/res/prog8lib/c64/syslib.p8 index bfc934b5e..c84d09884 100644 --- a/compiler/res/prog8lib/c64/syslib.p8 +++ b/compiler/res/prog8lib/c64/syslib.p8 @@ -600,7 +600,7 @@ _setup_raster_irq ora #%10000000 sta c64.SCROLY ; set most significant bit of raster position + lda #%00000001 - sta c64.IREQMASK ;enable raster interrupt signals from vic + sta c64.IREQMASK ; enable raster interrupt signals from vic rts }} } diff --git a/compiler/res/prog8lib/cx16/syslib.p8 b/compiler/res/prog8lib/cx16/syslib.p8 index ecc21c665..1679090fc 100644 --- a/compiler/res/prog8lib/cx16/syslib.p8 +++ b/compiler/res/prog8lib/cx16/syslib.p8 @@ -557,6 +557,7 @@ const ubyte EXTAPI_led_update = $0B const ubyte EXTAPI_mouse_set_position = $0C const ubyte EXTAPI_scnsiz = $0D const ubyte EXTAPI_kbd_leds = $0E +const ubyte EXTAPI_memory_decompress_from_func = $0F ; extapi16 call numbers const ubyte EXTAPI16_test = $00 diff --git a/compiler/src/prog8/compiler/astprocessing/SimplifiedAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/SimplifiedAstMaker.kt index 4902491b2..ade28e5fe 100644 --- a/compiler/src/prog8/compiler/astprocessing/SimplifiedAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/SimplifiedAstMaker.kt @@ -164,7 +164,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro } } - val assign = PtAssignment(srcAssign.position) + val assign = PtAssignment(srcAssign.position, srcAssign.origin==AssignmentOrigin.VARINIT) val multi = srcAssign.target.multi if(multi==null) { assign.add(transform(srcAssign.target)) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 0400092af..3892f152e 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,6 +1,13 @@ TODO ==== +- Look if the =0 variable initializations can be reduced further. (most notably for multi-value variable initialization). + See canSkipInitializationWith0()? + Remove it if there is another normal assignment after the initialization assignment, + that does not use the variable itself somewhere in the value, and the value doesn't contain a functioncall. + Set the "initializer" boolean to true on the first assignment that remains. + + - Make some of the target machine config externally configurable (for 1 new target, the existing ones should stay as they are for the time being) - add paypal donation button as well? @@ -70,6 +77,7 @@ Libraries --------- - Sorting module gnomesort_uw could be optimized more, rewrite in asm? Shellshort seems consistently faster even if most of the words are already sorted. - Add split-word array sorting routines to sorting module? +- add even more general raster irq routines to build some sort of "copper list" , like Oscar64 has? - pet32 target: make syslib more complete (missing kernal routines)? - need help with: PET disk routines (OPEN, SETLFS etc are not exposed as kernal calls) - fix the problems in atari target, and flesh out its libraries. @@ -80,7 +88,7 @@ Libraries Optimizations ------------- -- Look if the =0 variable initializations can be reduced further. (most notably for multi-value variable initialization) +- Compare output of some Oscar64 samples to what prog8 does for the equivalent code (see https://github.com/drmortalwombat/OscarTutorials/tree/main and https://github.com/drmortalwombat/oscar64/tree/main/samples) - Multi-value returns of normal subroutines: use cpu register A or AY for the first one and only start using virtual registers for the rest. Can FAC then be used for floats as well again? Those are now not supported for multi-value returns. - Optimize the IfExpression code generation to be more like regular if-else code. (both 6502 and IR) search for "TODO don't store condition as expression" diff --git a/examples/test.p8 b/examples/test.p8 index 54115c26e..5646ea2bd 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,14 +9,8 @@ main { ubyte @nozp @shared staticvar=51 sub start() { + ubyte a,b,c,d = multi4() ; TODO FIX IR CODEGEN - str shouldbestringarray = ["a", "b", "c"] - - ubyte x = math.rnd() - ubyte a,b = multi1() - ubyte c,d = multi2() - - x=irmen txt.print_ub(a) txt.spc() txt.print_ub(b) @@ -27,19 +21,24 @@ main { txt.nl() } - sub single() -> ubyte { - return cx16.r0L+cx16.r1L - } - asmsub multi1() -> ubyte @A, ubyte @Y { - %asm {{ - lda #1 - ldy #2 - rts - }} - } +; sub single() -> ubyte { +; return cx16.r0L+cx16.r1L +; } +; asmsub multi1() -> ubyte @A, ubyte @Y { +; %asm {{ +; lda #1 +; ldy #2 +; rts +; }} +; } +; +; sub multi2() -> ubyte, ubyte { +; cx16.r0++ +; return 3,4 +; } - sub multi2() -> ubyte, ubyte { + sub multi4() -> ubyte, ubyte, ubyte, ubyte { cx16.r0++ - return 3,4 + return 3,4,5,6 } } diff --git a/intermediate/src/prog8/intermediate/IRInstructions.kt b/intermediate/src/prog8/intermediate/IRInstructions.kt index 631dd8a9e..04f26ae27 100644 --- a/intermediate/src/prog8/intermediate/IRInstructions.kt +++ b/intermediate/src/prog8/intermediate/IRInstructions.kt @@ -71,7 +71,7 @@ CONTROL FLOW ------------ jump location - continue running at instruction at 'location' (label/memory address) jumpi reg1 - continue running at memory address in reg1 (indirect jump) -preparecall numparams - indicator that the next instructions are the param setup and function call/syscall with parameters +preparecall numparams - indicator that the next instructions are the param setup and function call/syscall with parameters, does nothing by itself calli reg1 - calls a subroutine (without arguments and without return valus) at memory addres in reg1 (indirect jsr) call label(argument register list) [: resultreg.type] - calls a subroutine with the given arguments and return value (optional). @@ -109,21 +109,21 @@ bstvs address - branch to location if Status bit Overf bgt reg1, value, address - jump to location in program given by location, if reg1 > immediate value (unsigned) blt reg1, value, address - jump to location in program given by location, if reg1 < immediate value (unsigned) bgtr reg1, reg2, address - jump to location in program given by location, if reg1 > reg2 (unsigned) -'bltr' reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (unsigned) ==> use bgtr with swapped operands +'bltr' reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (unsigned) ==> this opcode doesn't exist: use bgtr with swapped operands bge reg1, value, address - jump to location in program given by location, if reg1 >= immediate value (unsigned) ble reg1, value, address - jump to location in program given by location, if reg1 <= immediate value (unsigned) bger reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (unsigned) -'bler' reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (unsigned) ==> use bger with swapped operands +'bler' reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (unsigned) ==> this opcode doesn't exist: use bger with swapped operands (signed comparison branches:) bgts reg1, value, address - jump to location in program given by location, if reg1 > immediate value (signed) blts reg1, value, address - jump to location in program given by location, if reg1 < immediate value (signed) bgtsr reg1, reg2, address - jump to location in program given by location, if reg1 > reg2 (signed) -'bltsr' reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (signed) ==> use bgtsr with swapped operands +'bltsr' reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (signed) ==> this opcode doesn't exist: use bgtsr with swapped operands bges reg1, value, address - jump to location in program given by location, if reg1 >= immediate value (signed) bles reg1, value, address - jump to location in program given by location, if reg1 <= immediate value (signed) bgesr reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed) -'blesr' reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (signed) ==> use bgesr with swapped operands +'blesr' reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (signed) ==> this opcode doesn't exist: use bgesr with swapped operands ARITHMETIC @@ -194,13 +194,13 @@ lsrm address - shift memory right by 1 bits + se asrm address - shift memory right by 1 bits (signed) + set Carry to shifted bit lslm address - shift memory left by 1 bits + set Carry to shifted bit ror reg1 - rotate reg1 right by 1 bits, not using carry + set Carry to shifted bit -roxr reg1 - rotate reg1 right by 1 bits, using carry + set Carry to shifted bit +roxr reg1 - rotate reg1 right by 1 bits, using carry + set Carry to shifted bit (maps to 6502 CPU instruction ror) rol reg1 - rotate reg1 left by 1 bits, not using carry + set Carry to shifted bit -roxl reg1 - rotate reg1 left by 1 bits, using carry, + set Carry to shifted bit +roxl reg1 - rotate reg1 left by 1 bits, using carry, + set Carry to shifted bit (maps to 6502 CPU instruction rol) rorm address - rotate memory right by 1 bits, not using carry + set Carry to shifted bit -roxrm address - rotate memory right by 1 bits, using carry + set Carry to shifted bit +roxrm address - rotate memory right by 1 bits, using carry + set Carry to shifted bit (maps to 6502 CPU instruction ror) rolm address - rotate memory left by 1 bits, not using carry + set Carry to shifted bit -roxlm address - rotate memory left by 1 bits, using carry, + set Carry to shifted bit +roxlm address - rotate memory left by 1 bits, using carry, + set Carry to shifted bit (maps to 6502 CPU instruction rol) bit address - test bits in byte value at address, this is a special instruction available on other systems to optimize testing and branching on bits 7 and 6 @@ -483,7 +483,7 @@ val OpcodesThatSetStatusbitsButNotCarry = arrayOf( Opcode.OR, Opcode.XORM, Opcode.XORR, - Opcode.XOR, + Opcode.XOR ) val OpcodesThatDependOnCarry = arrayOf( @@ -494,7 +494,7 @@ val OpcodesThatDependOnCarry = arrayOf( Opcode.ROXL, Opcode.ROXLM, Opcode.ROXR, - Opcode.ROXRM, + Opcode.ROXRM ) val OpcodesThatSetStatusbits = OpcodesThatSetStatusbitsButNotCarry + OpcodesThatSetStatusbitsIncludingCarry