optimized codegen for logical expressions with simple right operand (such as c64.READST() & $40 )

This commit is contained in:
Irmen de Jong 2022-12-06 20:01:50 +01:00
parent a1d04f2aad
commit ca1089b881
2 changed files with 51 additions and 40 deletions

View File

@ -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
}

View File

@ -3,7 +3,6 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- why slow stack eval for "if c64.READST() & $40" ?
- regression test the various projects before release
...