mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
optimized 6502 codegen for logical expressions
This commit is contained in:
parent
cc174b7b85
commit
bda016bb3b
@ -2910,6 +2910,9 @@ $repeatLabel lda $counterVar
|
||||
}
|
||||
}
|
||||
|
||||
internal fun needAsaveForExpr(arg: Expression): Boolean =
|
||||
arg !is NumericLiteral && arg !is IdentifierReference && (arg !is DirectMemoryRead || !arg.isSimple)
|
||||
|
||||
private val subroutineExtrasCache = mutableMapOf<Subroutine, SubroutineExtraAsmInfo>()
|
||||
|
||||
internal fun subroutineExtra(sub: Subroutine): SubroutineExtraAsmInfo {
|
||||
|
@ -44,7 +44,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
"abs" -> funcAbs(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"any", "all" -> funcAnyAll(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"sgn" -> funcSgn(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"boolean" -> funcBoolean(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"boolean" -> funcBoolean(fcall, resultToStack, resultRegister, sscope)
|
||||
"rnd", "rndw" -> funcRnd(func, resultToStack, resultRegister, sscope)
|
||||
"sqrt16" -> funcSqrt16(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"rol" -> funcRol(fcall)
|
||||
@ -698,7 +698,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
private fun funcBoolean(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {
|
||||
private fun funcBoolean(fcall: IFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {
|
||||
when (val dt = fcall.args.single().inferType(program).getOr(DataType.UNDEFINED)) {
|
||||
in ByteDatatypes -> {
|
||||
assignAsmGen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.A, dt==DataType.BYTE)
|
||||
@ -884,7 +884,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
|
||||
} else {
|
||||
val reg = resultRegister ?: RegisterOrPair.AY
|
||||
var needAsave = needAsaveForOtherArg(fcall.args[0])
|
||||
var needAsave = asmgen.needAsaveForExpr(fcall.args[0])
|
||||
if(!needAsave) {
|
||||
val mr0 = fcall.args[0] as? DirectMemoryRead
|
||||
val mr1 = fcall.args[1] as? DirectMemoryRead
|
||||
@ -1133,7 +1133,4 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
private fun needAsaveForOtherArg(arg: Expression): Boolean =
|
||||
arg !is NumericLiteral && arg !is IdentifierReference && arg !is DirectMemoryRead
|
||||
|
||||
}
|
||||
|
@ -69,10 +69,6 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
(sub.parameters.size==1 && sub.parameters[0].type in IntegerDatatypes)
|
||||
|| (sub.parameters.size==2 && sub.parameters[0].type in ByteDatatypes && sub.parameters[1].type in ByteDatatypes)
|
||||
|
||||
private fun needAsaveForOtherArg(arg: Expression): Boolean =
|
||||
arg !is NumericLiteral && arg !is IdentifierReference && arg !is DirectMemoryRead
|
||||
|
||||
|
||||
internal fun translateFunctionCall(call: IFunctionCall, isExpression: Boolean) {
|
||||
// Output only the code to set up the parameters and perform the actual call
|
||||
// NOTE: does NOT output the code to deal with the result values!
|
||||
@ -112,10 +108,10 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
} else {
|
||||
// 2 byte params, second in Y, first in A
|
||||
argumentViaRegister(sub, IndexedValue(0, sub.parameters[0]), call.args[0], RegisterOrPair.A)
|
||||
if(needAsaveForOtherArg(call.args[1]))
|
||||
if(asmgen.needAsaveForExpr(call.args[1]))
|
||||
asmgen.out(" pha")
|
||||
argumentViaRegister(sub, IndexedValue(1, sub.parameters[1]), call.args[1], RegisterOrPair.Y)
|
||||
if(needAsaveForOtherArg(call.args[1]))
|
||||
if(asmgen.needAsaveForExpr(call.args[1]))
|
||||
asmgen.out(" pla")
|
||||
}
|
||||
} else {
|
||||
|
@ -2,6 +2,7 @@ package prog8.codegen.cpu6502.assignment
|
||||
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.getTempRegisterName
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.AsmGen
|
||||
@ -321,6 +322,63 @@ internal class AssignmentAsmGen(private val program: Program,
|
||||
if(!expr.inferType(program).isInteger)
|
||||
return false
|
||||
|
||||
// optimized code for logical expressions
|
||||
// TODO assume (hope) cx16.r9 isn't used for anything else during the use of this...
|
||||
if(expr.operator=="and") {
|
||||
val iDt = expr.left.inferType(program)
|
||||
val dt = iDt.getOrElse { throw AssemblyError("weird dt") }
|
||||
if (dt in ByteDatatypes) {
|
||||
val tmpReg = getTempRegisterName(iDt).joinToString(".")
|
||||
assignExpressionToVariable(expr.left, tmpReg, dt, expr.definingSubroutine)
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.A, dt==DataType.BYTE || dt==DataType.WORD)
|
||||
asmgen.out(" and $tmpReg")
|
||||
if(assign.target.datatype in ByteDatatypes)
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
else {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
||||
}
|
||||
return true
|
||||
}
|
||||
else throw AssemblyError("weird dt for and, expected byte $expr @${expr.position}")
|
||||
}
|
||||
else if(expr.operator=="or") {
|
||||
val iDt = expr.left.inferType(program)
|
||||
val dt = iDt.getOrElse { throw AssemblyError("weird dt") }
|
||||
if (dt in ByteDatatypes) {
|
||||
val tmpReg = getTempRegisterName(iDt).joinToString(".")
|
||||
assignExpressionToVariable(expr.left, tmpReg, dt, expr.definingSubroutine)
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.A, dt==DataType.BYTE || dt==DataType.WORD)
|
||||
asmgen.out(" ora $tmpReg")
|
||||
if(assign.target.datatype in ByteDatatypes)
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
else {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
||||
}
|
||||
return true
|
||||
}
|
||||
else throw AssemblyError("weird dt for or, expected byte $expr @${expr.position}")
|
||||
}
|
||||
else if(expr.operator=="xor") {
|
||||
val iDt = expr.left.inferType(program)
|
||||
val dt = iDt.getOrElse { throw AssemblyError("weird dt") }
|
||||
if (dt in ByteDatatypes) {
|
||||
val tmpReg = getTempRegisterName(iDt).joinToString(".")
|
||||
assignExpressionToVariable(expr.left, tmpReg, dt, expr.definingSubroutine)
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.A, dt==DataType.BYTE || dt==DataType.WORD)
|
||||
asmgen.out(" eor $tmpReg")
|
||||
if(assign.target.datatype in ByteDatatypes)
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
else {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
||||
}
|
||||
return true
|
||||
}
|
||||
else throw AssemblyError("weird dt for xor, expected byte $expr @${expr.position}")
|
||||
}
|
||||
|
||||
if(expr.operator!="+" && expr.operator!="-")
|
||||
return false
|
||||
|
||||
|
@ -3,8 +3,6 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- optimize logical expressions in attemptAssignOptimizedBinexpr()
|
||||
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
|
||||
...
|
||||
|
||||
|
||||
@ -19,6 +17,7 @@ Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Compiler:
|
||||
|
||||
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
|
||||
- vm: implement remaining sin/cos functions in math.p8
|
||||
- vm: somehow deal with asmsubs otherwise the vm IR can't fully encode all of prog8
|
||||
- vm: don't store symbol names in instructions to make optimizing the IR easier? but what about jumps to labels. And it's no longer readable by humans.
|
||||
|
@ -73,10 +73,10 @@ main {
|
||||
ubyte value
|
||||
uword wvalue
|
||||
|
||||
txt.print("short and with false (word): ")
|
||||
wvalue = funcw() and funcFalseWord() and funcw() and funcw()
|
||||
txt.print_uw(wvalue)
|
||||
txt.nl()
|
||||
; txt.print("short and with false (word): ")
|
||||
; wvalue = funcw() and funcFalseWord() and funcw() and funcw()
|
||||
; txt.print_uw(wvalue)
|
||||
; txt.nl()
|
||||
|
||||
txt.print("short and with false: ")
|
||||
value = func1(25) and funcFalse()
|
||||
|
Loading…
Reference in New Issue
Block a user