fix byte subtract from long

fix IR register check error for %ir segments
This commit is contained in:
Irmen de Jong
2025-12-06 13:56:23 +01:00
parent 0f433055a7
commit c693be0dd6
4 changed files with 70 additions and 37 deletions

View File

@@ -916,30 +916,18 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
else -> { else -> {
if(value in 1..255) { if(value in 1..255) {
asmgen.out(""" asmgen.out("""
lda $variable
sec sec
lda $variable
sbc #$value sbc #$value
sta $variable sta $variable
bcs + 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
lda $variable+1 lda $variable+1
sbc #>$value bne ++
sta $variable+1 lda $variable+2
bcs +
dec $variable+2
bne + bne +
dec $variable+3 dec $variable+3
+ dec $variable+2
+ dec $variable+1
+""") +""")
} else { } else {
val hex = value.toLongHex() val hex = value.toLongHex()

View File

@@ -66,7 +66,9 @@ Future Things and Ideas
IR/VM 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 - 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!) - 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?) - fix call() return value handling (... what's wrong with it again?)
@@ -102,7 +104,6 @@ IR/VM
- implement more TODOs in AssignmentGen - implement more TODOs in AssignmentGen
- do something with the 'split' tag on split word arrays - do something with the 'split' tag on split word arrays
- add more optimizations in IRPeepholeOptimizer, implement the TODOs in there at least - 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) - 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. 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. 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 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. - (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) - 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 - optimize inplaceLongShiftRight() for byte aligned cases

View File

@@ -1,20 +1,61 @@
%import textio %import textio
%zeropage basicsafe %zeropage basicsafe
main {
sub start() {
long @shared zz = 12345
zz <<= 9 main {
txt.print_l(zz)
txt.nl() long longvar = $100
zz = 12345
zz <<= 17 sub start() {
txt.print_l(zz)
txt.nl() longvar -= 5
zz = 12 txt.print_ulhex(longvar, true)
zz <<= 25
txt.print_l(zz)
txt.nl()
} }
} }
;
;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)
; }
; }
;}

View File

@@ -642,9 +642,11 @@ class RegistersUsed(
fun validate(allowed: Map<Int, IRDataType>, chunk: IRCodeChunkBase?) { fun validate(allowed: Map<Int, IRDataType>, chunk: IRCodeChunkBase?) {
for((reg, type) in regsTypes) { for((reg, type) in regsTypes) {
if(allowed[reg]==null) val allowedType = allowed[reg]
throw IllegalArgumentException("Reg type mismatch for register $reg type $type: no type known. CodeChunk=$chunk label ${chunk?.label}") // can't do this check because %ir {{ .. }} segments may contain registers that the compiler doesn't know about yet.
if(allowed[reg]!=type) // 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}") throw IllegalArgumentException("Reg type mismatch for register $reg type $type: expected ${allowed[reg]}. CodeChunk=$chunk label ${chunk?.label}")
} }
} }