diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index e0346a3a2..b3d1bc0c4 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -916,30 +916,18 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, else -> { if(value in 1..255) { asmgen.out(""" - lda $variable sec + lda $variable sbc #$value sta $variable - bcs + - dec $variable+1 - bne + - dec $variable+2 - bne + - dec $variable+3 -+""") - } else if(value in 1..65535) { - asmgen.out(""" - lda $variable - sec - sbc #<$value - sta $variable + bcs +++ lda $variable+1 - sbc #>$value - sta $variable+1 - bcs + - dec $variable+2 + bne ++ + lda $variable+2 bne + dec $variable+3 ++ dec $variable+2 ++ dec $variable+1 +""") } else { val hex = value.toLongHex() diff --git a/docs/source/todo.rst b/docs/source/todo.rst index d66f919e8..70b0424c9 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -66,7 +66,9 @@ Future Things and Ideas IR/VM ----- -- optimize float<0 float==0 float>0 to use SGN instruction? Check what code is generated for other data types. +- replace LOADIX/STOREIX with LOADFIELD/STOREFIELD +- extend the index range from 0-255 to 0-32767 in the LOADX, STOREX, LOADFIELD, STOREFIELD etc instructions (not compatible with 8 bit 6502, but the 68000 can use that) +- if float<0 / if word<0 uses sgn or load, but still use a bgt etc instruction after that with a #0 operand even though the sgn and load instructions sets the status bits already, so just use bstneg etc - add and sub instructions should modify the status flags so an explicit compare to zero can be avoided for example: if cx16.r0sL + cx16.r1sL <= 0 now compiles into: addr.b r10,r11 / bgts.b r10,#0,label - getting it in shape for code generation: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!) - fix call() return value handling (... what's wrong with it again?) @@ -102,7 +104,6 @@ IR/VM - implement more TODOs in AssignmentGen - do something with the 'split' tag on split word arrays - add more optimizations in IRPeepholeOptimizer, implement the TODOs in there at least -- extend the index range from 0-255 to 0-32767 in the LOADX, STOREX, LOADFIELD, STOREFIELD etc instructions (not compatible with 8 bit 6502, but the 68000 can use that) - idea: replace all scalar variables that are not @shared by an allocated register. Keep a table of the variable to register mapping (including the datatype) global initialization values are simply a list of LOAD instructions. Variables replaced include all subroutine parameters? Or not? So the only variables that remain as variables are arrays and strings. @@ -122,6 +123,7 @@ Libraries Optimizations ------------- +- peek(address + offset) and poke(address + offset, value) generate quite large asm segments. Optimize into subroutines for "indexed memory peek/pokes"? - (6502) optimize if sgn(value)<0: still does a compare with 0 even though SGN sets all status bits. - longvar = lptr^^ , lptr2^^=lptr^^ now go via temporary registers, optimize this to avoid using temps. (seems like it is dereferencing the pointer first and then assigning the intermediate value) - optimize inplaceLongShiftRight() for byte aligned cases diff --git a/examples/test.p8 b/examples/test.p8 index 7effd1883..2adb0198e 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,20 +1,61 @@ %import textio %zeropage basicsafe -main { - sub start() { - long @shared zz = 12345 - zz <<= 9 - txt.print_l(zz) - txt.nl() - zz = 12345 - zz <<= 17 - txt.print_l(zz) - txt.nl() - zz = 12 - zz <<= 25 - txt.print_l(zz) - txt.nl() +main { + + long longvar = $100 + + sub start() { + + longvar -= 5 + txt.print_ulhex(longvar, true) } } + + +; +;main { +; sub start() { +; ubyte[256] @shared array1 +; ubyte[256] @shared array2 +; ubyte[256] @shared array3 +; +; setvalues() +; readvalues() +; printvalues() +; +; sub setvalues() { +; poke(&array2 + 255, 99) +; poke(&array2 + 256, 88) +; poke(&array2 + $3000, 77) +; } +; +; sub readvalues() { +; %ir {{ +;loadm.b r1007,main.start.array2+255 +;storem.b r1007,$ff02 +;load.w r1009,main.start.array2 +;add.w r1009,#$0100 +;loadi.b r1008,r1009 +;storem.b r1008,$ff04 +;load.w r1011,main.start.array2 +;add.w r1011,#$3000 +;loadi.b r1010,r1011 +;storem.b r1010,$ff06 +;return +; }} +;; cx16.r0L = array2[255] +;; cx16.r1L = @(&array2 + 256) +;; cx16.r2L = @(&array2 + $3000) +; } +; +; sub printvalues() { +; txt.print_ub(cx16.r0L) +; txt.spc() +; txt.print_ub(cx16.r1L) +; txt.spc() +; txt.print_ub(cx16.r2L) +; } +; } +;} diff --git a/intermediate/src/prog8/intermediate/IRProgram.kt b/intermediate/src/prog8/intermediate/IRProgram.kt index cf4e9a67c..029b78bce 100644 --- a/intermediate/src/prog8/intermediate/IRProgram.kt +++ b/intermediate/src/prog8/intermediate/IRProgram.kt @@ -642,9 +642,11 @@ class RegistersUsed( fun validate(allowed: Map, chunk: IRCodeChunkBase?) { for((reg, type) in regsTypes) { - if(allowed[reg]==null) - throw IllegalArgumentException("Reg type mismatch for register $reg type $type: no type known. CodeChunk=$chunk label ${chunk?.label}") - if(allowed[reg]!=type) + val allowedType = allowed[reg] +// can't do this check because %ir {{ .. }} segments may contain registers that the compiler doesn't know about yet. +// if(allowedType==null) +// throw IllegalArgumentException("Reg type mismatch for register $reg type $type: no type known. CodeChunk=$chunk label ${chunk?.label}") + if(allowedType!=null && allowedType!=type) throw IllegalArgumentException("Reg type mismatch for register $reg type $type: expected ${allowed[reg]}. CodeChunk=$chunk label ${chunk?.label}") } }