optimized codegen for some more simple expressions with +/-

This commit is contained in:
Irmen de Jong 2022-06-06 22:54:54 +02:00
parent 3075578245
commit 0a65dfdd10
2 changed files with 149 additions and 54 deletions

View File

@ -318,7 +318,7 @@ internal class AssignmentAsmGen(private val program: Program,
// no orig ast assign target so can't use the workaround, so fallback to stack eval // no orig ast assign target so can't use the workaround, so fallback to stack eval
fallbackToStackEval(assign) fallbackToStackEval(assign)
} }
} else { } else if(!attemptAssignOptimizedBinexpr(value, assign)) {
// All remaining binary expressions just evaluate via the stack for now. // All remaining binary expressions just evaluate via the stack for now.
// (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here,
// because the code here is the implementation of exactly that...) // because the code here is the implementation of exactly that...)
@ -329,6 +329,143 @@ internal class AssignmentAsmGen(private val program: Program,
} }
} }
private fun attemptAssignOptimizedBinexpr(expr: BinaryExpression, assign: AsmAssignment): Boolean {
if(!expr.inferType(program).isInteger)
return false
if(expr.operator!="+" && expr.operator!="-")
return false
val dt = expr.inferType(program).getOrElse { throw AssemblyError("invalid dt") }
val left = expr.left
val right = expr.right
if(dt in ByteDatatypes) {
when (right) {
is IdentifierReference -> {
assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE)
val symname = asmgen.asmVariableName(right)
if(expr.operator=="+")
asmgen.out(" clc | adc $symname")
else
asmgen.out(" sec | sbc $symname")
assignRegisterByte(assign.target, CpuRegister.A)
return true
}
is NumericLiteral -> {
assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE)
if(expr.operator=="+")
asmgen.out(" clc | adc #${right.number.toHex()}")
else
asmgen.out(" sec | sbc #${right.number.toHex()}")
assignRegisterByte(assign.target, CpuRegister.A)
return true
}
else -> return false
}
} else if(dt in WordDatatypes) {
when (right) {
is AddressOf -> {
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
val symbol = asmgen.asmVariableName(right.identifier)
if(expr.operator=="+")
asmgen.out("""
clc
adc #<$symbol
pha
tya
adc #>$symbol
tay
pla""")
else
asmgen.out("""
sec
sbc #<$symbol
pha
tya
sbc #>$symbol
tay
pla""")
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
return true
}
is IdentifierReference -> {
val symname = asmgen.asmVariableName(right)
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
if(expr.operator=="+")
asmgen.out("""
clc
adc $symname
pha
tya
adc $symname+1
tay
pla""")
else
asmgen.out("""
sec
sbc $symname
pha
tya
sbc $symname+1
tay
pla""")
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
return true
}
is NumericLiteral -> {
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
if(expr.operator=="+") {
asmgen.out("""
clc
adc #<${right.number.toHex()}
pha
tya
adc #>${right.number.toHex()}
tay
pla""")
} else if(expr.operator=="-") {
asmgen.out("""
sec
sbc #<${right.number.toHex()}
pha
tya
sbc #>${right.number.toHex()}
tay
pla""")
}
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
return true
}
is TypecastExpression -> {
val castedValue = right.expression
if(right.type in WordDatatypes && castedValue.inferType(program).isBytes) {
if(castedValue is IdentifierReference) {
val castedSymname = asmgen.asmVariableName(castedValue)
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
if(expr.operator=="+")
asmgen.out("""
clc
adc $castedSymname
bcc +
iny
+""")
else
asmgen.out("""
sec
sbc $castedSymname
bcs +
dey
+""")
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
return true
}
}
}
else -> return false
}
}
return false
}
private fun fallbackToStackEval(assign: AsmAssignment) { private fun fallbackToStackEval(assign: AsmAssignment) {
// TODO DON'T STACK-EVAL... perhaps by using a temp var? so that it becomes augmentable assignment expression? // TODO DON'T STACK-EVAL... perhaps by using a temp var? so that it becomes augmentable assignment expression?
// or don't try to solve it here in this one case and rather rewrite the whole stack based value evaluation. // or don't try to solve it here in this one case and rather rewrite the whole stack based value evaluation.

View File

@ -33,64 +33,22 @@ main {
; mcCarthy() ; mcCarthy()
;test_stack.test() ;test_stack.test()
ubyte value = 0
ubyte one = 1 ubyte one = 1
ubyte two = 2 ubyte two = 2
ubyte[10] data = [11,22,33,4,5,6,7,8,9,10] uword onew = 1
uword twow = 2
ubyte[10] data = [1,2,3,4,5,6,7,8,9,10]
uword bitmapbuf = &data uword bitmapbuf = &data
; 11 22 33 ; @(bitmapbuf+onew) = 90+one
txt.print_ub(bitmapbuf[0]) ; @(bitmapbuf+twow) = 90+two
txt.spc() bitmapbuf += 5
txt.print_ub(bitmapbuf[1]) ; @(bitmapbuf-1) = 90+one
txt.spc() ; @(bitmapbuf-2) = 90+two
txt.print_ub(bitmapbuf[2]) @(bitmapbuf-onew) = 90+one
txt.nl() @(bitmapbuf-twow) = 90+two
rol(bitmapbuf[0])
rol(bitmapbuf[0])
txt.print_ub(bitmapbuf[0]) ; 44
txt.spc()
ror(bitmapbuf[0])
ror(bitmapbuf[0])
txt.print_ub(bitmapbuf[0]) ; 11
txt.nl()
; 22 44 66
txt.print_ub(bitmapbuf[0]*2)
txt.spc()
txt.print_ub(bitmapbuf[1]*2)
txt.spc()
txt.print_ub(bitmapbuf[2]*2)
txt.nl()
value = one+one+one+one+one
txt.print_ub(value) ; 5
txt.nl()
bitmapbuf[0] = one+one+one
bitmapbuf[0] = one+one+one
bitmapbuf[0] = one+one+one
bitmapbuf[1] = one+one
bitmapbuf[1] = one+one
bitmapbuf[1] = one+one
bitmapbuf[2] = one
bitmapbuf[2] = one
bitmapbuf[2] = one
bitmapbuf[3] = 42
bitmapbuf[2] += 100
bitmapbuf[2] -= 1
bitmapbuf[2] -= 1
bitmapbuf[2] -= 1
bitmapbuf[2] -= 1
; 3 2 97
txt.print_ub(bitmapbuf[0])
txt.spc()
txt.print_ub(bitmapbuf[1])
txt.spc()
txt.print_ub(bitmapbuf[2])
txt.nl()
ubyte value
for value in data { for value in data {
txt.print_ub(value) ; 3 2 97 42 5 6 7 8 9 10 txt.print_ub(value) ; 3 2 97 42 5 6 7 8 9 10
txt.spc() txt.spc()