From ca1089b8819d888ac9f6af1bd4c060c632684cb3 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 6 Dec 2022 20:01:50 +0100 Subject: [PATCH] optimized codegen for logical expressions with simple right operand (such as c64.READST() & $40 ) --- .../cpu6502/assignment/AssignmentAsmGen.kt | 90 +++++++++++-------- docs/source/todo.rst | 1 - 2 files changed, 51 insertions(+), 40 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 8e937b559..e1ce880b0 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -378,48 +378,60 @@ internal class AssignmentAsmGen(private val program: Program, if(!expr.inferType(program).isInteger) return false - if(expr.operator in setOf("&", "|", "^", "and", "or", "xor")) { - if(expr.left.inferType(program).isBytes && expr.right.inferType(program).isBytes && - expr.left.isSimple && expr.right.isSimple) { - if(expr.right is NumericLiteral || expr.right is IdentifierReference) - assignLogicalWithSimpleRightOperandByte(assign.target, expr.left, expr.operator, expr.right) - else if(expr.left is NumericLiteral || expr.left is IdentifierReference) - assignLogicalWithSimpleRightOperandByte(assign.target, expr.right, expr.operator, expr.left) - else { - assignExpressionToRegister(expr.left, RegisterOrPair.A, false) - asmgen.saveRegisterStack(CpuRegister.A, false) - assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE, expr.definingSubroutine) - asmgen.restoreRegisterStack(CpuRegister.A, false) - when (expr.operator) { - "&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1") - "|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1") - "^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1") - else -> throw AssemblyError("invalid operator") - } - assignRegisterByte(assign.target, CpuRegister.A) + fun simpleLogicalBytesExpr() { + // both left and right expression operands are simple. + if (expr.right is NumericLiteral || expr.right is IdentifierReference) + assignLogicalWithSimpleRightOperandByte(assign.target, expr.left, expr.operator, expr.right) + else if (expr.left is NumericLiteral || expr.left is IdentifierReference) + assignLogicalWithSimpleRightOperandByte(assign.target, expr.right, expr.operator, expr.left) + else { + assignExpressionToRegister(expr.left, RegisterOrPair.A, false) + asmgen.saveRegisterStack(CpuRegister.A, false) + assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE, expr.definingSubroutine) + asmgen.restoreRegisterStack(CpuRegister.A, false) + when (expr.operator) { + "&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1") + "|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1") + "^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1") + else -> throw AssemblyError("invalid operator") } - return true + assignRegisterByte(assign.target, CpuRegister.A) } - if(expr.left.inferType(program).isWords && expr.right.inferType(program).isWords && - expr.left.isSimple && expr.right.isSimple) { - if(expr.right is NumericLiteral || expr.right is IdentifierReference) - assignLogicalWithSimpleRightOperandWord(assign.target, expr.left, expr.operator, expr.right) - else if(expr.left is NumericLiteral || expr.left is IdentifierReference) - assignLogicalWithSimpleRightOperandWord(assign.target, expr.right, expr.operator, expr.left) - else { - assignExpressionToRegister(expr.left, RegisterOrPair.AY, false) - asmgen.saveRegisterStack(CpuRegister.A, false) - asmgen.saveRegisterStack(CpuRegister.Y, false) - assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_W1", DataType.UWORD, expr.definingSubroutine) - when (expr.operator) { - "&", "and" -> asmgen.out(" pla | and P8ZP_SCRATCH_W1+1 | tay | pla | and P8ZP_SCRATCH_W1") - "|", "or" -> asmgen.out(" pla | ora P8ZP_SCRATCH_W1+1 | tay | pla | ora P8ZP_SCRATCH_W1") - "^", "xor" -> asmgen.out(" pla | eor P8ZP_SCRATCH_W1+1 | tay | pla | eor P8ZP_SCRATCH_W1") - else -> throw AssemblyError("invalid operator") - } - assignRegisterpairWord(assign.target, RegisterOrPair.AY) + } + + fun simpleLogicalWordsExpr() { + // both left and right expression operands are simple. + if (expr.right is NumericLiteral || expr.right is IdentifierReference) + assignLogicalWithSimpleRightOperandWord(assign.target, expr.left, expr.operator, expr.right) + else if (expr.left is NumericLiteral || expr.left is IdentifierReference) + assignLogicalWithSimpleRightOperandWord(assign.target, expr.right, expr.operator, expr.left) + else { + assignExpressionToRegister(expr.left, RegisterOrPair.AY, false) + asmgen.saveRegisterStack(CpuRegister.A, false) + asmgen.saveRegisterStack(CpuRegister.Y, false) + assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_W1", DataType.UWORD, expr.definingSubroutine) + when (expr.operator) { + "&", "and" -> asmgen.out(" pla | and P8ZP_SCRATCH_W1+1 | tay | pla | and P8ZP_SCRATCH_W1") + "|", "or" -> asmgen.out(" pla | ora P8ZP_SCRATCH_W1+1 | tay | pla | ora P8ZP_SCRATCH_W1") + "^", "xor" -> asmgen.out(" pla | eor P8ZP_SCRATCH_W1+1 | tay | pla | eor P8ZP_SCRATCH_W1") + else -> throw AssemblyError("invalid operator") + } + assignRegisterpairWord(assign.target, RegisterOrPair.AY) + } + } + + if(expr.operator in setOf("&", "|", "^", "and", "or", "xor")) { + if (expr.left.inferType(program).isBytes && expr.right.inferType(program).isBytes) { + if (expr.right.isSimple) { + simpleLogicalBytesExpr() + return true + } + } + if (expr.left.inferType(program).isWords && expr.right.inferType(program).isWords) { + if (expr.right.isSimple) { + simpleLogicalWordsExpr() + return true } - return true } return false } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 265ba6569..0d0fdfe4f 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- why slow stack eval for "if c64.READST() & $40" ? - regression test the various projects before release ...