mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
implementing Rpn optimizations
This commit is contained in:
parent
5b0e1b4f9e
commit
e8bebe5a75
@ -48,11 +48,11 @@ class AsmGen6502Internal (
|
||||
private val forloopsAsmGen = ForLoopsAsmGen(program, this, zeropage)
|
||||
private val postincrdecrAsmGen = PostIncrDecrAsmGen(program, this)
|
||||
private val functioncallAsmGen = FunctionCallAsmGen(program, this)
|
||||
private val expressionsAsmGen = ExpressionsAsmGen(program, this, allocator)
|
||||
private val programGen = ProgramAndVarsGen(program, options, errors, symbolTable, functioncallAsmGen, this, allocator, zeropage)
|
||||
private val assignmentAsmGen = AssignmentAsmGen(program, symbolTable, this, allocator)
|
||||
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, symbolTable, this, assignmentAsmGen)
|
||||
private val rpnAssignmentAsmGen = RpnExpressionAsmGen(program, symbolTable, assignmentAsmGen, this)
|
||||
private val expressionsAsmGen = ExpressionsAsmGen(program, this, allocator)
|
||||
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen)
|
||||
private val rpnAssignmentAsmGen = RpnExpressionAsmGen(program, symbolTable, this)
|
||||
|
||||
fun compileToAssembly(): IAssemblyProgram? {
|
||||
|
||||
@ -1007,36 +1007,53 @@ $repeatLabel lda $counterVar
|
||||
}
|
||||
|
||||
internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression): Pair<PtExpression, PtExpression>? {
|
||||
if (pointerOffsetExpr is PtRpn) {
|
||||
return rpnAssignmentAsmGen.pointerViaIndexRegisterPossible(pointerOffsetExpr)
|
||||
}
|
||||
else if (pointerOffsetExpr is PtBinaryExpression) {
|
||||
if (pointerOffsetExpr.operator != "+") return null
|
||||
val leftDt = pointerOffsetExpr.left.type
|
||||
val rightDt = pointerOffsetExpr.left.type
|
||||
if(leftDt == DataType.UWORD && rightDt == DataType.UBYTE)
|
||||
return Pair(pointerOffsetExpr.left, pointerOffsetExpr.right)
|
||||
if(leftDt == DataType.UBYTE && rightDt == DataType.UWORD)
|
||||
return Pair(pointerOffsetExpr.right, pointerOffsetExpr.left)
|
||||
if(leftDt == DataType.UWORD && rightDt == DataType.UWORD) {
|
||||
// could be that the index was a constant numeric byte but converted to word, check that
|
||||
val constIdx = pointerOffsetExpr.right as? PtNumber
|
||||
if(constIdx!=null && constIdx.number.toInt()>=0 && constIdx.number.toInt()<=255) {
|
||||
return Pair(pointerOffsetExpr.left, PtNumber(DataType.UBYTE, constIdx.number, constIdx.position))
|
||||
}
|
||||
// could be that the index was typecasted into uword, check that
|
||||
val rightTc = pointerOffsetExpr.right as? PtTypeCast
|
||||
if(rightTc!=null && rightTc.value.type == DataType.UBYTE)
|
||||
return Pair(pointerOffsetExpr.left, rightTc.value)
|
||||
val leftTc = pointerOffsetExpr.left as? PtTypeCast
|
||||
if(leftTc!=null && leftTc.value.type == DataType.UBYTE)
|
||||
return Pair(pointerOffsetExpr.right, leftTc.value)
|
||||
val left: PtExpression
|
||||
val right: PtExpression
|
||||
val operator: String
|
||||
|
||||
when (pointerOffsetExpr) {
|
||||
is PtRpn -> {
|
||||
if(pointerOffsetExpr.children.size>3)
|
||||
return null // expression is too complex, we need just a pointer var + index
|
||||
val (leftNode, oper, rightNode) = pointerOffsetExpr.finalOperation()
|
||||
operator=oper.operator
|
||||
if (leftNode !is PtExpression || rightNode !is PtExpression) return null
|
||||
left = leftNode
|
||||
right = rightNode
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
operator = pointerOffsetExpr.operator
|
||||
left = pointerOffsetExpr.left
|
||||
right = pointerOffsetExpr.right
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
|
||||
if (operator != "+") return null
|
||||
val leftDt = left.type
|
||||
val rightDt = right.type
|
||||
if(leftDt == DataType.UWORD && rightDt == DataType.UBYTE)
|
||||
return Pair(left, right)
|
||||
if(leftDt == DataType.UBYTE && rightDt == DataType.UWORD)
|
||||
return Pair(right, left)
|
||||
if(leftDt == DataType.UWORD && rightDt == DataType.UWORD) {
|
||||
// could be that the index was a constant numeric byte but converted to word, check that
|
||||
val constIdx = right as? PtNumber
|
||||
if(constIdx!=null && constIdx.number.toInt()>=0 && constIdx.number.toInt()<=255) {
|
||||
return Pair(left, PtNumber(DataType.UBYTE, constIdx.number, constIdx.position))
|
||||
}
|
||||
// could be that the index was typecasted into uword, check that
|
||||
val rightTc = right as? PtTypeCast
|
||||
if(rightTc!=null && rightTc.value.type == DataType.UBYTE)
|
||||
return Pair(left, rightTc.value)
|
||||
val leftTc = left as? PtTypeCast
|
||||
if(leftTc!=null && leftTc.value.type == DataType.UBYTE)
|
||||
return Pair(right, leftTc.value)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
internal fun tryOptimizedPointerAccessWithA(expr: PtBinaryExpression, write: Boolean): Boolean {
|
||||
internal fun tryOptimizedPointerAccessWithA(addressExpr: PtExpression, operator: String, write: Boolean): Boolean {
|
||||
// optimize pointer,indexregister if possible
|
||||
|
||||
fun evalBytevalueWillClobberA(expr: PtExpression): Boolean {
|
||||
@ -1052,8 +1069,8 @@ $repeatLabel lda $counterVar
|
||||
}
|
||||
}
|
||||
|
||||
if(expr.operator=="+") {
|
||||
val ptrAndIndex = pointerViaIndexRegisterPossible(expr)
|
||||
if(operator=="+") {
|
||||
val ptrAndIndex = pointerViaIndexRegisterPossible(addressExpr)
|
||||
if(ptrAndIndex!=null) {
|
||||
val pointervar = ptrAndIndex.first as? PtIdentifier
|
||||
val target = if(pointervar==null) null else symbolTable.lookup(pointervar.name)!!.astNode
|
||||
@ -2882,7 +2899,8 @@ $repeatLabel lda $counterVar
|
||||
out(" sta P8ESTACK_LO,x | dex")
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
if(tryOptimizedPointerAccessWithA(expr.address as PtBinaryExpression, false)) {
|
||||
val addrExpr = expr.address as PtBinaryExpression
|
||||
if(tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
||||
if(pushResultOnEstack)
|
||||
out(" sta P8ESTACK_LO,x | dex")
|
||||
} else {
|
||||
@ -2890,7 +2908,8 @@ $repeatLabel lda $counterVar
|
||||
}
|
||||
}
|
||||
is PtRpn -> {
|
||||
if(rpnAssignmentAsmGen.tryOptimizedPointerAccessWithA(expr.address as PtRpn, false)) {
|
||||
val addrExpr = expr.address as PtRpn
|
||||
if(addrExpr.children.size==3 && tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
|
||||
if(pushResultOnEstack)
|
||||
out(" sta P8ESTACK_LO,x | dex")
|
||||
} else {
|
||||
|
@ -1,18 +1,14 @@
|
||||
package prog8.codegen.cpu6502
|
||||
|
||||
import prog8.code.SymbolTable
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.assignment.*
|
||||
|
||||
|
||||
internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
private val symbolTable: SymbolTable,
|
||||
private val asmgen: AsmGen6502Internal,
|
||||
private val assignAsmGen: AssignmentAsmGen) {
|
||||
|
||||
private val rpnAssignmentAsmGen = RpnExpressionAsmGen(program, symbolTable, assignAsmGen, asmgen)
|
||||
|
||||
internal fun translateFunctioncallExpression(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?): DataType? {
|
||||
return translateFunctioncall(fcall, discardResult = false, resultToStack = resultToStack, resultRegister = resultRegister)
|
||||
}
|
||||
@ -665,7 +661,29 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
return
|
||||
}
|
||||
}
|
||||
is PtRpn -> if(rpnAssignmentAsmGen.funcPokeW(fcall)) return
|
||||
is PtRpn -> {
|
||||
if(addrExpr.children.size==3) {
|
||||
// we want just one '+' operator
|
||||
val (left, oper, right) = addrExpr.finalOperation()
|
||||
if(oper.operator=="+" && left is PtIdentifier && right is PtNumber) {
|
||||
val varname = asmgen.asmVariableName(left)
|
||||
if(asmgen.isZpVar(left)) {
|
||||
// pointervar is already in the zero page, no need to copy
|
||||
asmgen.saveRegisterLocal(CpuRegister.X, fcall.definingISub()!!)
|
||||
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.AX)
|
||||
val index = right.number.toHex()
|
||||
asmgen.out("""
|
||||
ldy #$index
|
||||
sta ($varname),y
|
||||
txa
|
||||
iny
|
||||
sta ($varname),y""")
|
||||
asmgen.restoreRegisterLocal(CpuRegister.X)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier && addrExpr.right is PtNumber) {
|
||||
val varname = asmgen.asmVariableName(addrExpr.left as PtIdentifier)
|
||||
@ -695,6 +713,10 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
private fun funcPeekW(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
|
||||
fun fallback() {
|
||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
|
||||
asmgen.out(" jsr prog8_lib.func_peekw")
|
||||
}
|
||||
when(val addrExpr = fcall.args[0]) {
|
||||
is PtNumber -> {
|
||||
val addr = addrExpr.number.toHex()
|
||||
@ -720,12 +742,29 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
tay
|
||||
pla""")
|
||||
}
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
|
||||
asmgen.out(" jsr prog8_lib.func_peekw")
|
||||
}
|
||||
} else fallback()
|
||||
}
|
||||
is PtRpn -> {
|
||||
if(addrExpr.children.size==3) {
|
||||
// must be 3 (one '+' operator), otherwise expression is too complex for this
|
||||
val (left, oper, right) = addrExpr.finalOperation()
|
||||
if(oper.operator=="+" && left is PtIdentifier && right is PtNumber) {
|
||||
val varname = asmgen.asmVariableName(left)
|
||||
if(asmgen.isZpVar(left)) {
|
||||
// pointervar is already in the zero page, no need to copy
|
||||
val index = right.number.toHex()
|
||||
asmgen.out("""
|
||||
ldy #$index
|
||||
lda ($varname),y
|
||||
pha
|
||||
iny
|
||||
lda ($varname),y
|
||||
tay
|
||||
pla""")
|
||||
} else fallback()
|
||||
} else fallback()
|
||||
} else fallback()
|
||||
}
|
||||
is PtRpn -> rpnAssignmentAsmGen.funcPeekW(fcall, resultToStack, resultRegister)
|
||||
is PtBinaryExpression -> {
|
||||
if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier && addrExpr.right is PtNumber) {
|
||||
val varname = asmgen.asmVariableName(addrExpr.left as PtIdentifier)
|
||||
@ -740,19 +779,10 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
lda ($varname),y
|
||||
tay
|
||||
pla""")
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
|
||||
asmgen.out(" jsr prog8_lib.func_peekw")
|
||||
}
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
|
||||
asmgen.out(" jsr prog8_lib.func_peekw")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
|
||||
asmgen.out(" jsr prog8_lib.func_peekw")
|
||||
} else fallback()
|
||||
} else fallback()
|
||||
}
|
||||
else -> fallback()
|
||||
}
|
||||
|
||||
if(resultToStack){
|
||||
|
@ -25,7 +25,7 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
|
||||
when(expression) {
|
||||
is PtPrefix -> translateExpression(expression)
|
||||
is PtBinaryExpression -> translateExpression(expression)
|
||||
is PtRpn -> translateExpression(expression)
|
||||
is PtRpn -> translateRpnExpression(expression)
|
||||
is PtArrayIndexer -> translateExpression(expression)
|
||||
is PtTypeCast -> translateExpression(expression)
|
||||
is PtAddressOf -> translateExpression(expression)
|
||||
@ -245,7 +245,7 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateExpression(expr: PtRpn) {
|
||||
private fun translateRpnExpression(expr: PtRpn) {
|
||||
// Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED!
|
||||
val oper = expr.finalOperator()
|
||||
val leftDt = oper.leftType
|
||||
@ -265,6 +265,8 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
|
||||
return translateCompareStrings(expr.finalLeftOperand() as PtExpression, oper.operator, expr.finalRightOperand() as PtExpression)
|
||||
}
|
||||
|
||||
// TODO: RPN: add the other optimizations that BinaryExpression has, to avoid eval stack usage
|
||||
|
||||
// any other expression
|
||||
if((leftDt in ByteDatatypes && rightDt !in ByteDatatypes)
|
||||
|| (leftDt in WordDatatypes && rightDt !in WordDatatypes))
|
||||
|
@ -9,11 +9,11 @@ import prog8.codegen.cpu6502.returnsWhatWhere
|
||||
|
||||
|
||||
internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
private val symbolTable: SymbolTable,
|
||||
symbolTable: SymbolTable,
|
||||
private val asmgen: AsmGen6502Internal,
|
||||
private val allocator: VariableAllocator) {
|
||||
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen, allocator)
|
||||
private val rpnAssignmentAsmGen = RpnExpressionAsmGen(program, symbolTable, this, asmgen)
|
||||
private val rpnAssignmentAsmGen = RpnExpressionAsmGen(program, symbolTable, asmgen)
|
||||
|
||||
fun translate(assignment: PtAssignment) {
|
||||
val target = AsmAssignTarget.fromAstAssignment(assignment.target, assignment.definingISub(), asmgen)
|
||||
@ -145,14 +145,16 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
assignMemoryByte(assign.target, null, value.address as PtIdentifier)
|
||||
}
|
||||
is PtRpn -> {
|
||||
if(rpnAssignmentAsmGen.tryOptimizedPointerAccessWithA(value.address as PtRpn, false)) {
|
||||
val addrExpr = value.address as PtRpn
|
||||
if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
} else {
|
||||
assignViaExprEval(value.address)
|
||||
}
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
if(asmgen.tryOptimizedPointerAccessWithA(value.address as PtBinaryExpression, false)) {
|
||||
val addrExpr = value.address as PtBinaryExpression
|
||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
} else {
|
||||
assignViaExprEval(value.address)
|
||||
@ -313,7 +315,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
is PtRpn -> {
|
||||
if(!rpnAssignmentAsmGen.attemptAssignOptimizedExpr(value, assign)) {
|
||||
if(!rpnAssignmentAsmGen.attemptAssignOptimizedExpr(assign)) {
|
||||
// All remaining binary expressions just evaluate via the stack for now.
|
||||
// TODO: For RPN expressions this should never occur anymore and the eval stack should be removed when we achieve this
|
||||
// (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here,
|
||||
@ -920,7 +922,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
assignMemoryByteIntoWord(target, null, value.address as PtIdentifier)
|
||||
}
|
||||
is PtRpn -> {
|
||||
if(rpnAssignmentAsmGen.tryOptimizedPointerAccessWithA(value.address as PtRpn, false)) {
|
||||
val addrExpr = value.address as PtRpn
|
||||
if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
} else {
|
||||
@ -928,7 +931,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
if(asmgen.tryOptimizedPointerAccessWithA(value.address as PtBinaryExpression, false)) {
|
||||
val addrExpr = value.address as PtBinaryExpression
|
||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
} else {
|
||||
@ -2849,11 +2853,11 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
asmgen.storeAIntoPointerVar(addressExpr)
|
||||
}
|
||||
addressExpr is PtRpn -> {
|
||||
if(!rpnAssignmentAsmGen.tryOptimizedPointerAccessWithA(addressExpr, true))
|
||||
if(addressExpr.children.size!=3 || !asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.finalOperator().operator, true))
|
||||
storeViaExprEval()
|
||||
}
|
||||
addressExpr is PtBinaryExpression -> {
|
||||
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, true))
|
||||
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.operator, true))
|
||||
storeViaExprEval()
|
||||
}
|
||||
else -> storeViaExprEval()
|
||||
|
@ -1,129 +1,21 @@
|
||||
package prog8.codegen.cpu6502.assignment
|
||||
|
||||
import prog8.code.SymbolTable
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.CpuRegister
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.RegisterOrPair
|
||||
import prog8.code.ast.PtProgram
|
||||
import prog8.code.ast.PtRpn
|
||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||
|
||||
internal class RpnExpressionAsmGen(
|
||||
val program: PtProgram,
|
||||
val symbolTable: SymbolTable,
|
||||
val assignmentAsmGen: AssignmentAsmGen,
|
||||
val asmgen: AsmGen6502Internal
|
||||
) {
|
||||
|
||||
internal fun tryOptimizedPointerAccessWithA(expr: PtRpn, write: Boolean): Boolean {
|
||||
// optimize pointer,indexregister if possible
|
||||
|
||||
fun evalBytevalueWillClobberA(expr: PtExpression): Boolean {
|
||||
val dt = expr.type
|
||||
if(dt != DataType.UBYTE && dt != DataType.BYTE)
|
||||
return true
|
||||
return when(expr) {
|
||||
is PtIdentifier -> false
|
||||
is PtNumber -> false
|
||||
is PtMemoryByte -> expr.address !is PtIdentifier && expr.address !is PtNumber
|
||||
is PtTypeCast -> evalBytevalueWillClobberA(expr.value)
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
if(expr.finalOperator().operator=="+") {
|
||||
val ptrAndIndex = asmgen.pointerViaIndexRegisterPossible(expr)
|
||||
if(ptrAndIndex!=null) {
|
||||
val pointervar = ptrAndIndex.first as? PtIdentifier
|
||||
val target = if(pointervar==null) null else symbolTable.lookup(pointervar.name)!!.astNode
|
||||
when(target) {
|
||||
is PtLabel -> {
|
||||
asmgen.assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
asmgen.out(" lda ${asmgen.asmSymbolName(pointervar!!)},y")
|
||||
return true
|
||||
}
|
||||
is IPtVariable, null -> {
|
||||
if(write) {
|
||||
if(pointervar!=null && asmgen.isZpVar(pointervar)) {
|
||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||
if(saveA)
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
if(saveA)
|
||||
asmgen.out(" pla")
|
||||
asmgen.out(" sta (${asmgen.asmSymbolName(pointervar)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.first) || evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||
if(saveA)
|
||||
asmgen.out(" pha")
|
||||
if(ptrAndIndex.second.isSimple()) {
|
||||
asmgen. assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
|
||||
asmgen.assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
if(saveA)
|
||||
asmgen.out(" pla")
|
||||
asmgen.out(" sta (P8ZP_SCRATCH_W2),y")
|
||||
} else {
|
||||
asmgen.pushCpuStack(DataType.UBYTE, ptrAndIndex.second)
|
||||
asmgen.assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, true)
|
||||
if(saveA)
|
||||
asmgen.out(" pla")
|
||||
asmgen.out(" sta (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(pointervar!=null && asmgen.isZpVar(pointervar)) {
|
||||
asmgen.assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
asmgen.out(" lda (${asmgen.asmSymbolName(pointervar)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
if(ptrAndIndex.second.isSimple()) {
|
||||
asmgen.assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
|
||||
asmgen.assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
|
||||
asmgen.out(" lda (P8ZP_SCRATCH_W2),y")
|
||||
} else {
|
||||
asmgen.pushCpuStack(DataType.UBYTE, ptrAndIndex.second)
|
||||
asmgen.assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
|
||||
asmgen.restoreRegisterStack(CpuRegister.Y, false)
|
||||
asmgen.out(" lda (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
else -> throw AssemblyError("invalid pointervar $pointervar")
|
||||
}
|
||||
}
|
||||
}
|
||||
fun attemptAssignOptimizedExpr(assign: AsmAssignment): Boolean {
|
||||
val value = assign.source.expression as PtRpn
|
||||
println("TODO: RPN: optimized assignment ${value.position}") // TODO RPN: optimized assignment
|
||||
// NOTE: don't forgot to evaluate the rest of the RPN expr as well
|
||||
return false
|
||||
}
|
||||
|
||||
fun attemptAssignOptimizedExpr(expr: PtRpn, assign: AsmAssignment): Boolean {
|
||||
println("TODO: RPN: optimized assignment ${expr.position}") // TODO RPN: optimized assignment
|
||||
return false
|
||||
}
|
||||
|
||||
fun funcPeekW(
|
||||
fcall: PtBuiltinFunctionCall,
|
||||
resultToStack: Boolean,
|
||||
resultRegister: RegisterOrPair?
|
||||
) {
|
||||
println("TODO: RPN: peekw optimized pointer+index ${fcall.position}") // TODO RPN: peekw optimized pointer+index
|
||||
// val (left, oper, right) = addrExpr.finalOperation()
|
||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
|
||||
asmgen.out(" jsr prog8_lib.func_peekw")
|
||||
}
|
||||
|
||||
fun funcPokeW(fcall: PtBuiltinFunctionCall): Boolean {
|
||||
println("TODO: RPN: pokew optimized pointer+index ${fcall.position}") // TODO RPN: pokew optimized pointer+index
|
||||
// val (left, oper, right) = addrExpr.finalOperation()
|
||||
// for now: fall through
|
||||
return false
|
||||
}
|
||||
|
||||
fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtRpn): Pair<PtExpression, PtExpression>? {
|
||||
TODO("RPN determine pointer+index via reg.") // however, is this ever getting called from RPN code?
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
BRANCH: Fix the TODO RPN routines to be optimized assembly
|
||||
BRANCH: Fix the TODO RPN routines to be optimized assembly in RpnExpressionAsmGen.kt
|
||||
|
||||
Implement RPN codegen for IR.
|
||||
|
||||
For next minor release
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -3,6 +3,8 @@
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
; $1e4 size
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
@ -10,17 +12,20 @@ main {
|
||||
uword xx=32
|
||||
cx16.r0L = 3
|
||||
|
||||
if cx16.r0L in "derp" {
|
||||
xx++
|
||||
}
|
||||
cx16.r0 = peekw(xx + 44)
|
||||
@(xx+44) = cx16.r0L
|
||||
|
||||
xx = xx+(3*func(xx)+xx*2*cx16.r0L)
|
||||
txt.print_uw(xx)
|
||||
; if cx16.r0L in "derp" {
|
||||
; xx++
|
||||
; }
|
||||
;
|
||||
; xx = xx+(3*func(xx)+xx*2*cx16.r0L)
|
||||
; txt.print_uw(xx)
|
||||
test_stack.test()
|
||||
}
|
||||
|
||||
sub func(uword value) -> uword {
|
||||
value ++
|
||||
return value
|
||||
}
|
||||
; sub func(uword value) -> uword {
|
||||
; value ++
|
||||
; return value
|
||||
; }
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user