mirror of
https://github.com/irmen/prog8.git
synced 2025-11-03 04:17:16 +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)
|
val varname = asmgen.asmVariableName(pointer)
|
||||||
asmgen.assignExpressionToRegister(result.second, RegisterOrPair.Y)
|
asmgen.assignExpressionToRegister(result.second, RegisterOrPair.Y)
|
||||||
asmgen.out(" lda ($varname),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()
|
||||||
}
|
}
|
||||||
else -> fallback()
|
else -> fallback()
|
||||||
@@ -1112,6 +1114,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
lda ($varname),y
|
lda ($varname),y
|
||||||
tay
|
tay
|
||||||
txa""")
|
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()
|
||||||
}
|
}
|
||||||
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?) {
|
private fun funcPeekL(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
||||||
// TODO optimize for the simple cases
|
// TODO optimize for the simple cases
|
||||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
|
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
|
; -- read the byte value on the address in AY, into A
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_W1+1
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
from_scratchW1
|
||||||
ldy #0
|
ldy #0
|
||||||
lda (P8ZP_SCRATCH_W1),y
|
lda (P8ZP_SCRATCH_W1),y
|
||||||
rts
|
rts
|
||||||
@@ -444,6 +445,7 @@ func_peekw .proc
|
|||||||
; -- read the word value on the address in AY, into AY
|
; -- read the word value on the address in AY, into AY
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_W1+1
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
from_scratchW1
|
||||||
ldy #0
|
ldy #0
|
||||||
lda (P8ZP_SCRATCH_W1),y
|
lda (P8ZP_SCRATCH_W1),y
|
||||||
pha
|
pha
|
||||||
@@ -458,6 +460,7 @@ func_peekl .proc
|
|||||||
; -- read the ;pmg value on the address in AY, into R0:R1
|
; -- read the ;pmg value on the address in AY, into R0:R1
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_W1+1
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
from_scratchW1
|
||||||
ldy #0
|
ldy #0
|
||||||
lda (P8ZP_SCRATCH_W1),y
|
lda (P8ZP_SCRATCH_W1),y
|
||||||
sta cx16.r0
|
sta cx16.r0
|
||||||
|
|||||||
@@ -297,6 +297,17 @@ _after:
|
|||||||
val peek = FunctionCallExpression(IdentifierReference(listOf("peekbool"), arrayIndexedExpression.position), mutableListOf(address), arrayIndexedExpression.position)
|
val peek = FunctionCallExpression(IdentifierReference(listOf("peekbool"), arrayIndexedExpression.position), mutableListOf(address), arrayIndexedExpression.position)
|
||||||
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, peek, parent))
|
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) {
|
} else if(arrayVar.datatype.sub==BaseDataType.FLOAT) {
|
||||||
// use peekf/pokef
|
// use peekf/pokef
|
||||||
if(parent is AssignTarget) {
|
if(parent is AssignTarget) {
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
- optimized translation for pokeX and peekX if address = pointer + uwordoffset.
|
||||||
|
|
||||||
|
|
||||||
STRUCTS and TYPED POINTERS
|
STRUCTS and TYPED POINTERS
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
- implement the remaining TODO's in PointerAssignmentsGen.
|
- implement the remaining TODO's in PointerAssignmentsGen.
|
||||||
- optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
|
- 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)
|
- 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')
|
- implement even more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO) (add to documentation as well, paragraph 'Structs')
|
||||||
- support @nosplit pointer arrays?
|
- 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.
|
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?
|
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)
|
- 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
|
- 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
|
- 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
|
- 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.
|
; Here is the actual multiplexing routine.
|
||||||
; it's a raster irq just after the start of the sprite,
|
; it's a raster irq just after the start of the sprite,
|
||||||
; that updates the Y position of all the sprits,
|
; 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,
|
; 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.
|
; and moves the sprites back to the top of the screen.
|
||||||
sub multiplexer() -> bool {
|
sub multiplexer() -> bool {
|
||||||
@@ -51,12 +51,15 @@ irq {
|
|||||||
first_sprite_X = 0
|
first_sprite_X = 0
|
||||||
sprites.set_sprites_Y(sprites_Y)
|
sprites.set_sprites_Y(sprites_Y)
|
||||||
while c64.RASTER != cx16.r2 {
|
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
|
sprites.set_sprites_X(first_sprite_X) ; we can now update the X positions without risk of sprite tearing
|
||||||
system_irq = true
|
system_irq = true
|
||||||
} else {
|
} 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)
|
sprites.set_sprites_Y(sprites_Y)
|
||||||
|
c64.SPXY[0]++
|
||||||
}
|
}
|
||||||
|
|
||||||
sys.set_rasterline(sprites_Y+1)
|
sys.set_rasterline(sprites_Y+1)
|
||||||
|
|||||||
@@ -3,45 +3,17 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
long @shared lv1 = -9999
|
^^bool flags
|
||||||
; txt.print_uw(lsw(lv1))
|
^^word words
|
||||||
; txt.spc()
|
^^long longs
|
||||||
; 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)
|
|
||||||
|
|
||||||
|
|
||||||
txt.nl()
|
; TODO optimized translation of the peekX and pokeX calls:
|
||||||
txt.nl()
|
if flags[cx16.r0]
|
||||||
lv1 = -9876543
|
flags[cx16.r0] = true
|
||||||
conv.str_ub0(123)
|
if words[cx16.r0]!=0
|
||||||
txt.print(conv.str_l(lv1))
|
words[cx16.r0] = 9990
|
||||||
txt.spc()
|
if longs[cx16.r0]!=0
|
||||||
txt.print(conv.string_out)
|
longs[cx16.r0] = 999999
|
||||||
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()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user