mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +00:00 
			
		
		
		
	avoid fallback JSR peek for common case pointer+offset
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 82 KiB  | 
@@ -1067,6 +1067,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
 | 
			
		||||
                    val varname = asmgen.asmVariableName(pointer)
 | 
			
		||||
                    asmgen.assignExpressionToRegister(result.second, RegisterOrPair.Y)
 | 
			
		||||
                    asmgen.out("  lda  ($varname),y")
 | 
			
		||||
                } else if(addrExpr.operator in arrayOf("+", "-") && addrExpr.left is PtIdentifier) {
 | 
			
		||||
                    readValueFromPointerPlusOrMinOffset(addrExpr.left as PtIdentifier, addrExpr.operator, addrExpr.right, BaseDataType.BOOL)
 | 
			
		||||
                } else fallback()
 | 
			
		||||
            }
 | 
			
		||||
            else -> fallback()
 | 
			
		||||
@@ -1112,6 +1114,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
 | 
			
		||||
                        lda  ($varname),y
 | 
			
		||||
                        tay
 | 
			
		||||
                        txa""")
 | 
			
		||||
                } else if(addrExpr.operator in arrayOf("+", "-") && addrExpr.left is PtIdentifier) {
 | 
			
		||||
                    readValueFromPointerPlusOrMinOffset(addrExpr.left as PtIdentifier, addrExpr.operator, addrExpr.right, BaseDataType.UWORD)
 | 
			
		||||
                } else fallback()
 | 
			
		||||
            }
 | 
			
		||||
            else -> fallback()
 | 
			
		||||
@@ -1129,6 +1133,37 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun readValueFromPointerPlusOrMinOffset(ptr: PtIdentifier, operator: String, offset: PtExpression, dt: BaseDataType) {
 | 
			
		||||
        val varname = asmgen.asmVariableName(ptr)
 | 
			
		||||
        asmgen.assignExpressionToRegister(offset, RegisterOrPair.AY)
 | 
			
		||||
        if(operator=="+")
 | 
			
		||||
            asmgen.out("""
 | 
			
		||||
                clc
 | 
			
		||||
                adc  $varname
 | 
			
		||||
                sta  P8ZP_SCRATCH_W1
 | 
			
		||||
                tya
 | 
			
		||||
                adc  $varname+1
 | 
			
		||||
                sta  P8ZP_SCRATCH_W1+1""")
 | 
			
		||||
        else
 | 
			
		||||
            asmgen.out("""
 | 
			
		||||
                sec
 | 
			
		||||
                sbc  $varname
 | 
			
		||||
                sta  P8ZP_SCRATCH_W1
 | 
			
		||||
                tya
 | 
			
		||||
                sbc  $varname+1
 | 
			
		||||
                sta  P8ZP_SCRATCH_W1+1""")
 | 
			
		||||
 | 
			
		||||
        if (dt.isByteOrBool) {
 | 
			
		||||
            if(asmgen.isTargetCpu(CpuType.CPU65C02)) {
 | 
			
		||||
                asmgen.out("  lda  (P8ZP_SCRATCH_W1)")
 | 
			
		||||
            } else {
 | 
			
		||||
                asmgen.out("  ldy  #0 |  lda  (P8ZP_SCRATCH_W1),y")
 | 
			
		||||
            }
 | 
			
		||||
        } else if(dt.isWord) {
 | 
			
		||||
            asmgen.out("  jsr  prog8_lib.func_peekw.from_scratchW1")
 | 
			
		||||
        } else throw AssemblyError("unsupported type for peek $dt")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun funcPeekL(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
 | 
			
		||||
        // TODO optimize for the simple cases
 | 
			
		||||
        asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
 | 
			
		||||
 
 | 
			
		||||
@@ -435,6 +435,7 @@ func_peek   .proc
 | 
			
		||||
	; -- read the byte value on the address in AY, into A
 | 
			
		||||
	sta  P8ZP_SCRATCH_W1
 | 
			
		||||
	sty  P8ZP_SCRATCH_W1+1
 | 
			
		||||
from_scratchW1
 | 
			
		||||
	ldy  #0
 | 
			
		||||
	lda  (P8ZP_SCRATCH_W1),y
 | 
			
		||||
	rts
 | 
			
		||||
@@ -444,6 +445,7 @@ func_peekw   .proc
 | 
			
		||||
	; -- read the word value on the address in AY, into AY
 | 
			
		||||
	sta  P8ZP_SCRATCH_W1
 | 
			
		||||
	sty  P8ZP_SCRATCH_W1+1
 | 
			
		||||
from_scratchW1
 | 
			
		||||
	ldy  #0
 | 
			
		||||
	lda  (P8ZP_SCRATCH_W1),y
 | 
			
		||||
	pha
 | 
			
		||||
@@ -458,6 +460,7 @@ func_peekl   .proc
 | 
			
		||||
	; -- read the ;pmg value on the address in AY, into R0:R1
 | 
			
		||||
	sta  P8ZP_SCRATCH_W1
 | 
			
		||||
	sty  P8ZP_SCRATCH_W1+1
 | 
			
		||||
from_scratchW1
 | 
			
		||||
	ldy  #0
 | 
			
		||||
	lda  (P8ZP_SCRATCH_W1),y
 | 
			
		||||
	sta  cx16.r0
 | 
			
		||||
 
 | 
			
		||||
@@ -297,6 +297,17 @@ _after:
 | 
			
		||||
                    val peek = FunctionCallExpression(IdentifierReference(listOf("peekbool"), arrayIndexedExpression.position), mutableListOf(address), arrayIndexedExpression.position)
 | 
			
		||||
                    return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, peek, parent))
 | 
			
		||||
                }
 | 
			
		||||
            } else if(arrayVar.datatype.sub==BaseDataType.LONG) {
 | 
			
		||||
                // use peekl/pokel
 | 
			
		||||
                if(parent is AssignTarget) {
 | 
			
		||||
                    val assignment = parent.parent as Assignment
 | 
			
		||||
                    val args = mutableListOf(address, assignment.value)
 | 
			
		||||
                    val poke = FunctionCallStatement(IdentifierReference(listOf("pokel"), arrayIndexedExpression.position), args, false, arrayIndexedExpression.position)
 | 
			
		||||
                    return listOf(IAstModification.ReplaceNode(assignment, poke, assignment.parent))
 | 
			
		||||
                } else {
 | 
			
		||||
                    val peek = FunctionCallExpression(IdentifierReference(listOf("peekl"), arrayIndexedExpression.position), mutableListOf(address), arrayIndexedExpression.position)
 | 
			
		||||
                    return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, peek, parent))
 | 
			
		||||
                }
 | 
			
		||||
            } else if(arrayVar.datatype.sub==BaseDataType.FLOAT) {
 | 
			
		||||
                // use peekf/pokef
 | 
			
		||||
                if(parent is AssignTarget) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,15 @@
 | 
			
		||||
TODO
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
- optimized translation for pokeX and peekX if address =  pointer + uwordoffset.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
STRUCTS and TYPED POINTERS
 | 
			
		||||
--------------------------
 | 
			
		||||
 | 
			
		||||
- implement the remaining TODO's in PointerAssignmentsGen.
 | 
			
		||||
- optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
 | 
			
		||||
- optimize the float copying in assignIndexedPointer() (also word?)
 | 
			
		||||
- optimize the float copying in assignIndexedPointer() (also word and long?)
 | 
			
		||||
- optimize augmented assignments to indexed pointer targets like sprptr[2]^^.y++  (these are now not performend in-place but as a regular assignment)
 | 
			
		||||
- implement even more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO) (add to documentation as well, paragraph 'Structs')
 | 
			
		||||
- support @nosplit pointer arrays?
 | 
			
		||||
@@ -24,6 +27,8 @@ Future Things and Ideas
 | 
			
		||||
  This will break some existing programs that depend on value wrap arounds, but gives more intuitive constant number handling.
 | 
			
		||||
  Can give descriptive error message for old syntax that still includes the type name?
 | 
			
		||||
- improve ANTLR grammar with better error handling (as suggested by Qwen AI)
 | 
			
		||||
- add documentation for more library modules instead of just linking to the source code
 | 
			
		||||
- add an Index to the documentation
 | 
			
		||||
- allow memory() to occur in array initializer
 | 
			
		||||
- when a complete block is removed because unused, suppress all info messages about everything in the block being removed
 | 
			
		||||
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ irq {
 | 
			
		||||
    ; Here is the actual multiplexing routine.
 | 
			
		||||
    ; it's a raster irq just after the start of the sprite,
 | 
			
		||||
    ; that updates the Y position of all the sprits,
 | 
			
		||||
    ; and registers a new rater irq for that next row of sprites.
 | 
			
		||||
    ; and registers a new raster irq for that next row of sprites.
 | 
			
		||||
    ; If the bottom of the screen is reached, it resets the X position of the sprites as well,
 | 
			
		||||
    ; and moves the sprites back to the top of the screen.
 | 
			
		||||
    sub multiplexer() -> bool {
 | 
			
		||||
@@ -48,15 +48,18 @@ irq {
 | 
			
		||||
            sprites_Y = sprites.sprites_Y_start
 | 
			
		||||
            first_sprite_X++
 | 
			
		||||
            if first_sprite_X >= 340
 | 
			
		||||
                first_sprite_X =0
 | 
			
		||||
                first_sprite_X = 0
 | 
			
		||||
            sprites.set_sprites_Y(sprites_Y)
 | 
			
		||||
            while c64.RASTER != cx16.r2 {
 | 
			
		||||
                ; wait until raster line after sprite has been fully drawn (at least 24 lines down)
 | 
			
		||||
                ; wait until raster line after sprites have been fully drawn (at least 24 lines down)
 | 
			
		||||
            }
 | 
			
		||||
            sprites.set_sprites_X(first_sprite_X)        ; we can now update the X positions without risk of sprite tearing
 | 
			
		||||
            system_irq = true
 | 
			
		||||
        } else {
 | 
			
		||||
            ; only set the new Y positions. But it's possible to change other attributes as well ofcourse (colors, x-position, data)
 | 
			
		||||
            ; but raster timing is critical for that if you want to avoid tearing and glitches. Can probably not be done here at this raster position...
 | 
			
		||||
            sprites.set_sprites_Y(sprites_Y)
 | 
			
		||||
            c64.SPXY[0]++
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sys.set_rasterline(sprites_Y+1)
 | 
			
		||||
 
 | 
			
		||||
@@ -3,45 +3,17 @@
 | 
			
		||||
 | 
			
		||||
main {
 | 
			
		||||
    sub start() {
 | 
			
		||||
        long @shared lv1 = -9999
 | 
			
		||||
;        txt.print_uw(lsw(lv1))
 | 
			
		||||
;        txt.spc()
 | 
			
		||||
;        txt.print_w(lv1 as word)
 | 
			
		||||
;        txt.spc()
 | 
			
		||||
;        txt.print_uw(lv1 as uword)
 | 
			
		||||
;        txt.spc()
 | 
			
		||||
;        txt.print_b(lv1 as byte)
 | 
			
		||||
;        txt.spc()
 | 
			
		||||
;        txt.print_ub(lv1 as ubyte)
 | 
			
		||||
;        txt.spc()
 | 
			
		||||
;        txt.print_w(msw(lv1 << 8) as word)
 | 
			
		||||
;        txt.spc()
 | 
			
		||||
;        txt.print_w(lsw(lv1 >> 8) as word)
 | 
			
		||||
        ^^bool flags
 | 
			
		||||
        ^^word words
 | 
			
		||||
        ^^long longs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        txt.nl()
 | 
			
		||||
        txt.nl()
 | 
			
		||||
        lv1 = -9876543
 | 
			
		||||
        conv.str_ub0(123)
 | 
			
		||||
        txt.print(conv.str_l(lv1))
 | 
			
		||||
        txt.spc()
 | 
			
		||||
        txt.print(conv.string_out)
 | 
			
		||||
        txt.nl()
 | 
			
		||||
        lv1 = 123456
 | 
			
		||||
        txt.print(conv.str_l(lv1))
 | 
			
		||||
        txt.spc()
 | 
			
		||||
        txt.print(conv.string_out)
 | 
			
		||||
        txt.nl()
 | 
			
		||||
        lv1 = -2147483647
 | 
			
		||||
        txt.print(conv.str_l(lv1))
 | 
			
		||||
        txt.spc()
 | 
			
		||||
        txt.print(conv.string_out)
 | 
			
		||||
        txt.nl()
 | 
			
		||||
        lv1 = 2147483647
 | 
			
		||||
        txt.print(conv.str_l(lv1))
 | 
			
		||||
        txt.spc()
 | 
			
		||||
        txt.print(conv.string_out)
 | 
			
		||||
        txt.nl()
 | 
			
		||||
 | 
			
		||||
        ; TODO optimized translation of the peekX and pokeX calls:
 | 
			
		||||
        if flags[cx16.r0]
 | 
			
		||||
            flags[cx16.r0] = true
 | 
			
		||||
        if words[cx16.r0]!=0
 | 
			
		||||
            words[cx16.r0] = 9990
 | 
			
		||||
        if longs[cx16.r0]!=0
 | 
			
		||||
            longs[cx16.r0] = 999999
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user