added sys.waitrasterline() routine like sys.waitvsync() but wait for a given raster line

optimize uword <= $xx00 into msb(uword)<$xx
This commit is contained in:
Irmen de Jong
2025-09-23 01:00:24 +02:00
parent fd62fe7511
commit 54fa72fa98
7 changed files with 109 additions and 16 deletions
@@ -427,13 +427,18 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
}
}
fun isPowerOfTwo(number: Double): Boolean {
// fun isPowerOfTwo(number: Double): Boolean {
// val intValue = number.toInt()
// return intValue > 0 && (intValue and (intValue - 1)) == 0
// }
fun isFactorOf256(number: Double): Boolean {
val intValue = number.toInt()
return intValue > 0 && (intValue and (intValue - 1)) == 0
return intValue > 0 && (intValue and (intValue shl 8)) == 0
}
if (leftDt.isUnsignedWord && rightVal!=null) {
if ((rightVal.number == 255.0 && expr.operator == ">") || (rightVal.number == 256.0 && expr.operator == ">=")) {
if (expr.operator == ">" && rightVal.number == 255.0 || expr.operator == ">=" && rightVal.number == 256.0) {
// uword > 255 --> msb(value)!=0
// uword >= 256 --> msb(value)!=0
expr.operator = "!="
@@ -441,27 +446,54 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
expr.right = NumericLiteral(BaseDataType.UBYTE, 0.0, expr.right.position)
expr.linkParents(parent)
}
else if(expr.operator==">=" && rightVal.number >= 256.0 && isPowerOfTwo(rightVal.number)) {
val msbFraction = floor(rightVal.number / 256.0)
else if(expr.operator==">=" && isFactorOf256(rightVal.number)) {
// uword >= $xx00 --> msb(value)>=xx
val msbFraction = floor(rightVal.number / 256.0)
expr.operator = ">="
expr.left = FunctionCallExpression(IdentifierReference(listOf("msb"), expr.left.position), mutableListOf(expr.left), expr.left.position)
expr.right = NumericLiteral(BaseDataType.UBYTE, msbFraction, expr.right.position)
expr.linkParents(parent)
}
else if(expr.operator==">" && rightVal.number >= 255.0 && isPowerOfTwo(rightVal.number+1)) {
val msbFraction = floor((rightVal.number+1) / 256.0)
// uword > $xxFF --> msb(value)>=xx
expr.operator = ">="
else if(expr.operator==">" && isFactorOf256(rightVal.number+1)) {
// uword > $xxFF --> msb(value)>xx
val msbFraction = floor((rightVal.number) / 256.0)
expr.operator = ">"
expr.left = FunctionCallExpression(IdentifierReference(listOf("msb"), expr.left.position), mutableListOf(expr.left), expr.left.position)
expr.right = NumericLiteral(BaseDataType.UBYTE, msbFraction, expr.right.position)
expr.linkParents(parent)
}
else if(expr.operator == "<" && rightVal.number == 256.0 || expr.operator == "<=" && rightVal.number == 255.0) {
// uword < 256 --> msb(value)==0
// uword <= 255 --> msb(value)==0
// OK!
expr.operator = "=="
expr.left = FunctionCallExpression(IdentifierReference(listOf("msb"), expr.left.position), mutableListOf(expr.left), expr.left.position)
expr.right = NumericLiteral(BaseDataType.UBYTE, 0.0, expr.right.position)
expr.linkParents(parent)
}
else if(expr.operator == "<" && isFactorOf256(rightVal.number)) {
// uword < $xx00 --> msb(value)<xx
val msbFraction = floor(rightVal.number / 256.0)
expr.operator = "<"
expr.left = FunctionCallExpression(IdentifierReference(listOf("msb"), expr.left.position), mutableListOf(expr.left), expr.left.position)
expr.right = NumericLiteral(BaseDataType.UBYTE, msbFraction, expr.right.position)
expr.linkParents(parent)
}
else if(expr.operator=="<=" && isFactorOf256(rightVal.number+1)) {
// uword <= $xxFF --> msb(value)<=xx
val msbFraction = floor((rightVal.number) / 256.0)
expr.operator = "<="
expr.left = FunctionCallExpression(IdentifierReference(listOf("msb"), expr.left.position), mutableListOf(expr.left), expr.left.position)
expr.right = NumericLiteral(BaseDataType.UBYTE, msbFraction, expr.right.position)
expr.linkParents(parent)
}
}
return noModifications
}
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
if(arrayIndexedExpression.indexer.constIndex()==0) {
if(arrayIndexedExpression.plainarrayvar!=null) {
+20
View File
@@ -704,6 +704,26 @@ _loop lda P8ZP_SCRATCH_W1
}}
}
asmsub waitrasterline(uword line @AY) {
; -- CPU busy wait until the given raster line is reached
%asm {{
cpy #0
bne _larger
- cmp c64.RASTER
bne -
bit c64.SCROLY
bmi -
rts
_larger
cmp c64.RASTER
bne _larger
bit c64.SCROLY
bpl _larger
rts
}}
}
asmsub internal_stringcopy(str source @R0, str target @AY) clobbers (A,Y) {
; Called when the compiler wants to assign a string value to another string.
%asm {{
+20
View File
@@ -713,6 +713,26 @@ _loop lda P8ZP_SCRATCH_W1
}}
}
asmsub waitrasterline(uword line @AY) {
; -- CPU busy wait until the given raster line is reached
%asm {{
cpy #0
bne _larger
- cmp c64.RASTER
bne -
bit c64.SCROLY
bmi -
rts
_larger
cmp c64.RASTER
bne _larger
bit c64.SCROLY
bpl _larger
rts
}}
}
asmsub internal_stringcopy(str source @R0, str target @AY) clobbers (A,Y) {
; Called when the compiler wants to assign a string value to another string.
%asm {{
+20
View File
@@ -1781,6 +1781,26 @@ _loop lda P8ZP_SCRATCH_W1
}}
}
asmsub waitrasterline(uword line @AY) {
; -- CPU busy wait until the given raster line is reached
%asm {{
cpy #0
bne _larger
- cmp cx16.VERA_SCANLINE_L
bne -
bit cx16.VERA_IEN
bvs -
rts
_larger
cmp cx16.VERA_SCANLINE_L
bne _larger
bit cx16.VERA_IEN
bvc _larger
rts
}}
}
asmsub internal_stringcopy(str source @R0, str target @AY) clobbers (A,Y) {
; Called when the compiler wants to assign a string value to another string.
%asm {{
+6 -6
View File
@@ -19,18 +19,18 @@ Structs and Pointers
if it is a pointer to a struct type.
The compiler tries its best to give a descriptive error message but sometimes there is still a
parser limitation that has to be worked around at the moment. For example, this pointer arithmetic
indexing syntax is not supported right now and will result in a parse error::
indexing syntax is not supported right now *to assign to* and will result in a parse error (note that
using it as an expression value does work correctly)::
^^Node np
np[2].field = 9999
np[2].field = 9999 ; cannot assign to this yet
ubyte value = np[2].field ; this does work though.
To work around this (and similar) cases you'll have to break up the expression in multiple steps,
in this case something like::
^^Node thirdnode = &&np[2]
thirdnode.field = 9999
*Note: this example is not regular array indexing syntax, it's pointer arithmetic by indexing on the pointer itself. Regular array syntax is supported just fine for arrays containing pointers etc.*
^^Node thenode = &&np[2]
thenode.field = 9999
+1
View File
@@ -161,6 +161,7 @@ Libraries
Optimizations
-------------
- while c64.RASTER!=lsb(line) or c64.SCROLY&$80==0 { } generates code that really wants to use 1/0 boolean values as intermediates. why? can't that be optimized away? I want it to use th BIT instruction on the msb even
- check that expressions such as targetvar = value1 + value2 , targetvar = value1 ^ value2 etc. use the target variable directly and not use needless temp var / registers
- Port benchmarks from https://thred.github.io/c-bench-64/ to prog8 and see how it stacks up.
- Since fixing the missing zp-var initialization, programs grew in size again because STZ's reappeared. Can we add more intelligent (and correct!) optimizations to remove those STZs that might be redundant again?
+1 -1
View File
@@ -3,4 +3,4 @@ org.gradle.console=rich
org.gradle.parallel=true
org.gradle.daemon=true
kotlin.code.style=official
version=12.0-BETA2
version=12.0-BETA3