mirror of
https://github.com/irmen/prog8.git
synced 2025-08-09 19:25:22 +00:00
more optimal if expression code
This commit is contained in:
@@ -66,6 +66,7 @@ What does Prog8 provide?
|
|||||||
- conditional branches that map 1:1 to cpu status flags
|
- conditional branches that map 1:1 to cpu status flags
|
||||||
- ``when`` statement to provide a concise jump table alternative to if/elseif chains
|
- ``when`` statement to provide a concise jump table alternative to if/elseif chains
|
||||||
- ``in`` expression for concise and efficient multi-value/containment check
|
- ``in`` expression for concise and efficient multi-value/containment check
|
||||||
|
- ``defer`` statement to help write concise and robust subroutine cleanup logic
|
||||||
- several specialized built-in functions such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror``
|
- several specialized built-in functions such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror``
|
||||||
- various powerful built-in libraries to do I/O, number conversions, graphics and more
|
- various powerful built-in libraries to do I/O, number conversions, graphics and more
|
||||||
- inline assembly allows you to have full control when every cycle or byte matters
|
- inline assembly allows you to have full control when every cycle or byte matters
|
||||||
|
@@ -645,7 +645,7 @@ internal class AssignmentAsmGen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignIfExpression(target: AsmAssignTarget, expr: PtIfExpression) {
|
private fun assignIfExpression(target: AsmAssignTarget, expr: PtIfExpression) {
|
||||||
// TODO dont store condition as expression result but just use the flags, like a normal PtIfElse translation does
|
// TODO don't store condition as expression result but just use the flags, like a normal PtIfElse translation does
|
||||||
require(target.datatype==expr.type)
|
require(target.datatype==expr.type)
|
||||||
val falseLabel = asmgen.makeLabel("ifexpr_false")
|
val falseLabel = asmgen.makeLabel("ifexpr_false")
|
||||||
val endLabel = asmgen.makeLabel("ifexpr_end")
|
val endLabel = asmgen.makeLabel("ifexpr_end")
|
||||||
@@ -654,32 +654,27 @@ internal class AssignmentAsmGen(
|
|||||||
when(expr.type) {
|
when(expr.type) {
|
||||||
in ByteDatatypesWithBoolean -> {
|
in ByteDatatypesWithBoolean -> {
|
||||||
assignExpressionToRegister(expr.truevalue, RegisterOrPair.A, false)
|
assignExpressionToRegister(expr.truevalue, RegisterOrPair.A, false)
|
||||||
assignRegisterByte(target, CpuRegister.A, false, false)
|
|
||||||
asmgen.jmp(endLabel)
|
asmgen.jmp(endLabel)
|
||||||
asmgen.out(falseLabel)
|
asmgen.out(falseLabel)
|
||||||
assignExpressionToRegister(expr.falsevalue, RegisterOrPair.A, false)
|
assignExpressionToRegister(expr.falsevalue, RegisterOrPair.A, false)
|
||||||
assignRegisterByte(target, CpuRegister.A, false, false)
|
|
||||||
asmgen.out(endLabel)
|
asmgen.out(endLabel)
|
||||||
|
assignRegisterByte(target, CpuRegister.A, false, false)
|
||||||
}
|
}
|
||||||
in WordDatatypes -> {
|
in WordDatatypes -> {
|
||||||
assignExpressionToRegister(expr.truevalue, RegisterOrPair.AY, false)
|
assignExpressionToRegister(expr.truevalue, RegisterOrPair.AY, false)
|
||||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
|
||||||
asmgen.jmp(endLabel)
|
asmgen.jmp(endLabel)
|
||||||
asmgen.out(falseLabel)
|
asmgen.out(falseLabel)
|
||||||
assignExpressionToRegister(expr.falsevalue, RegisterOrPair.AY, false)
|
assignExpressionToRegister(expr.falsevalue, RegisterOrPair.AY, false)
|
||||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
|
||||||
asmgen.out(endLabel)
|
asmgen.out(endLabel)
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
val trueSrc = AsmAssignSource.fromAstSource(expr.truevalue, program, asmgen)
|
assignExpressionToRegister(expr.truevalue, RegisterOrPair.FAC1, true)
|
||||||
val assignTrue = AsmAssignment(trueSrc, target, program.memsizer, expr.position)
|
|
||||||
translateNormalAssignment(assignTrue, expr.definingISub())
|
|
||||||
asmgen.jmp(endLabel)
|
asmgen.jmp(endLabel)
|
||||||
asmgen.out(falseLabel)
|
asmgen.out(falseLabel)
|
||||||
val falseSrc = AsmAssignSource.fromAstSource(expr.falsevalue, program, asmgen)
|
assignExpressionToRegister(expr.falsevalue, RegisterOrPair.FAC1, true)
|
||||||
val assignFalse = AsmAssignment(falseSrc, target, program.memsizer, expr.position)
|
|
||||||
translateNormalAssignment(assignFalse, expr.definingISub())
|
|
||||||
asmgen.out(endLabel)
|
asmgen.out(endLabel)
|
||||||
|
asmgen.assignRegister(RegisterOrPair.FAC1, target)
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("weird dt")
|
else -> throw AssemblyError("weird dt")
|
||||||
}
|
}
|
||||||
|
@@ -91,7 +91,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(ifExpr: PtIfExpression): ExpressionCodeResult {
|
private fun translate(ifExpr: PtIfExpression): ExpressionCodeResult {
|
||||||
// TODO dont store condition as expression result but just use the flags, like a normal PtIfElse translation does
|
// TODO don't store condition as expression result but just use the flags, like a normal PtIfElse translation does
|
||||||
val condTr = translateExpression(ifExpr.condition)
|
val condTr = translateExpression(ifExpr.condition)
|
||||||
val trueTr = translateExpression(ifExpr.truevalue)
|
val trueTr = translateExpression(ifExpr.truevalue)
|
||||||
val falseTr = translateExpression(ifExpr.falsevalue)
|
val falseTr = translateExpression(ifExpr.falsevalue)
|
||||||
|
@@ -93,11 +93,12 @@ Features
|
|||||||
still able to directly use memory addresses and ROM subroutines,
|
still able to directly use memory addresses and ROM subroutines,
|
||||||
and inline assembly to have full control when every register, cycle or byte matters
|
and inline assembly to have full control when every register, cycle or byte matters
|
||||||
- Variables are all allocated statically, no memory allocation overhead
|
- Variables are all allocated statically, no memory allocation overhead
|
||||||
|
- Variable data types include signed and unsigned bytes and words, arrays, strings.
|
||||||
- Conditional branches for status flags that map 1:1 to processor branch instructions for optimal efficiency
|
- Conditional branches for status flags that map 1:1 to processor branch instructions for optimal efficiency
|
||||||
- ``when`` statement to avoid if-else chains
|
- ``when`` statement to avoid if-else chains
|
||||||
- ``in`` expression for concise and efficient multi-value/containment test
|
- ``in`` expression for concise and efficient multi-value/containment test
|
||||||
|
- ``defer`` statement to help write concise and robust subroutine cleanup logic
|
||||||
- Several specialized built-in functions, such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror``
|
- Several specialized built-in functions, such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror``
|
||||||
- Variable data types include signed and unsigned bytes and words, arrays, strings.
|
|
||||||
- Various powerful built-in libraries to do I/O, number conversions, graphics and more
|
- Various powerful built-in libraries to do I/O, number conversions, graphics and more
|
||||||
- Floating point math is supported on certain compiler targets.
|
- Floating point math is supported on certain compiler targets.
|
||||||
- Easy and highly efficient integration with external subroutines and ROM routines on the target systems.
|
- Easy and highly efficient integration with external subroutines and ROM routines on the target systems.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- Optimize the IfExpression code generation to be more like regular if-else code. (both 6502 and IR)
|
- Optimize the IfExpression code generation to be more like regular if-else code. (both 6502 and IR) (assignIfExpression / translate(ifExpr: PtIfExpression))
|
||||||
|
|
||||||
|
|
||||||
Improve register load order in subroutine call args assignments:
|
Improve register load order in subroutine call args assignments:
|
||||||
|
@@ -1,54 +1,24 @@
|
|||||||
%import textio
|
|
||||||
%import floats
|
%import floats
|
||||||
|
%import textio
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
uword res1 = allocate(111)
|
ubyte[4] values
|
||||||
defer deallocate(res1)
|
uword[4] wvalues
|
||||||
uword res2 = allocate(222)
|
float[4] fvalues
|
||||||
if res2==0
|
cx16.r0L = 0
|
||||||
return
|
cx16.r1L = 3
|
||||||
defer deallocate(res2)
|
values[cx16.r0L+2] = if cx16.r1L>2 99 else 111
|
||||||
|
wvalues[cx16.r0L+2] = if cx16.r1L>2 9999 else 1111
|
||||||
|
fvalues[cx16.r0L+2] = if cx16.r1L>2 9.99 else 1.111
|
||||||
|
|
||||||
if not process1(res1, res2)
|
txt.print_ub(values[2])
|
||||||
return
|
|
||||||
if not process2(res1, res2)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sub allocate(uword arg) -> uword {
|
|
||||||
; if arg==222
|
|
||||||
; return 0
|
|
||||||
txt.print("allocate ")
|
|
||||||
txt.print_uw(4000+arg)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
return 4000+arg
|
txt.print_uw(wvalues[2])
|
||||||
}
|
|
||||||
|
|
||||||
sub deallocate(uword arg) {
|
|
||||||
txt.print("dealloc ")
|
|
||||||
txt.print_uw(arg)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
}
|
floats.print(fvalues[2])
|
||||||
|
|
||||||
sub process1(uword arg1, uword arg2) -> bool {
|
|
||||||
txt.print("process1 ")
|
|
||||||
txt.print_uw(arg1)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(arg2)
|
|
||||||
txt.nl()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
sub process2(uword arg1, uword arg2) -> bool {
|
|
||||||
txt.print("process2 ")
|
|
||||||
txt.print_uw(arg1)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(arg2)
|
|
||||||
txt.nl()
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user